Skip to content

Commit 8c927a8

Browse files
committed
Save serialized traces to scylla
1 parent e1afdc0 commit 8c927a8

File tree

4 files changed

+239
-107
lines changed

4 files changed

+239
-107
lines changed

pkg/api/event_handlers.go

+142-107
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"encoding/hex"
88
"errors"
99
"fmt"
10+
"github.com/tonkeeper/tongo/abi"
1011
"go.uber.org/zap"
1112
"golang.org/x/exp/slices"
1213
"net/http"
@@ -390,29 +391,37 @@ func (h *Handler) EmulateMessageToAccountEvent(ctx context.Context, request *oas
390391
if err != nil {
391392
return nil, toError(http.StatusBadRequest, err)
392393
}
393-
configBase64, err := h.storage.TrimmedConfigBase64()
394-
if err != nil {
395-
return nil, toError(http.StatusInternalServerError, err)
396-
}
397-
options := []txemulator.TraceOption{
398-
txemulator.WithAccountsSource(h.storage),
399-
txemulator.WithConfigBase64(configBase64),
400-
txemulator.WithLimit(1100),
401-
}
402-
if !params.IgnoreSignatureCheck.Value {
403-
options = append(options, txemulator.WithSignatureCheck())
404-
}
405-
emulator, err := txemulator.NewTraceBuilder(options...)
406-
if err != nil {
407-
return nil, toError(http.StatusInternalServerError, err)
408-
}
409-
tree, err := emulator.Run(ctx, m)
410-
if err != nil {
411-
return nil, toProperEmulationError(err)
412-
}
413-
trace, err := emulatedTreeToTrace(ctx, h.executor, h.storage, tree, emulator.FinalStates(), nil, h.configPool)
414-
if err != nil {
415-
return nil, toError(http.StatusInternalServerError, err)
394+
hash, err := c.HashString()
395+
trace, _, err := h.storage.GetTraceWithState(ctx, hash)
396+
if trace == nil {
397+
configBase64, err := h.storage.TrimmedConfigBase64()
398+
if err != nil {
399+
return nil, toError(http.StatusInternalServerError, err)
400+
}
401+
options := []txemulator.TraceOption{
402+
txemulator.WithAccountsSource(h.storage),
403+
txemulator.WithConfigBase64(configBase64),
404+
txemulator.WithLimit(1100),
405+
}
406+
if !params.IgnoreSignatureCheck.Value {
407+
options = append(options, txemulator.WithSignatureCheck())
408+
}
409+
emulator, err := txemulator.NewTraceBuilder(options...)
410+
if err != nil {
411+
return nil, toError(http.StatusInternalServerError, err)
412+
}
413+
tree, err := emulator.Run(ctx, m)
414+
if err != nil {
415+
return nil, toProperEmulationError(err)
416+
}
417+
trace, err = emulatedTreeToTrace(ctx, h.executor, h.storage, tree, emulator.FinalStates(), nil, h.configPool)
418+
if err != nil {
419+
return nil, toError(http.StatusInternalServerError, err)
420+
}
421+
err = h.storage.SaveTraceWithState(hash, trace, []abi.MethodInvocation{}, 24*time.Hour)
422+
if err != nil {
423+
fmt.Println("not saved to scylla: ", err)
424+
}
416425
}
417426
actions, err := bath.FindActions(ctx, trace, bath.WithInformationSource(h.storage))
418427
if err != nil {
@@ -437,33 +446,41 @@ func (h *Handler) EmulateMessageToEvent(ctx context.Context, request *oas.Emulat
437446
}
438447
trace, prs := h.mempoolEmulate.traces.Get(hash)
439448
if !prs {
440-
var m tlb.Message
441-
if err := tlb.Unmarshal(c, &m); err != nil {
442-
return nil, toError(http.StatusBadRequest, err)
443-
}
444-
configBase64, err := h.storage.TrimmedConfigBase64()
445-
if err != nil {
446-
return nil, toError(http.StatusInternalServerError, err)
447-
}
448-
options := []txemulator.TraceOption{
449-
txemulator.WithAccountsSource(h.storage),
450-
txemulator.WithConfigBase64(configBase64),
451-
}
452-
if !params.IgnoreSignatureCheck.Value {
453-
options = append(options, txemulator.WithSignatureCheck())
454-
}
449+
hs, _ := c.HashString()
450+
trace, _, err = h.storage.GetTraceWithState(ctx, hs)
451+
if trace == nil {
452+
var m tlb.Message
453+
if err := tlb.Unmarshal(c, &m); err != nil {
454+
return nil, toError(http.StatusBadRequest, err)
455+
}
456+
configBase64, err := h.storage.TrimmedConfigBase64()
457+
if err != nil {
458+
return nil, toError(http.StatusInternalServerError, err)
459+
}
460+
options := []txemulator.TraceOption{
461+
txemulator.WithAccountsSource(h.storage),
462+
txemulator.WithConfigBase64(configBase64),
463+
}
464+
if !params.IgnoreSignatureCheck.Value {
465+
options = append(options, txemulator.WithSignatureCheck())
466+
}
455467

456-
emulator, err := txemulator.NewTraceBuilder(options...)
457-
if err != nil {
458-
return nil, toError(http.StatusInternalServerError, err)
459-
}
460-
tree, err := emulator.Run(ctx, m)
461-
if err != nil {
462-
return nil, toProperEmulationError(err)
463-
}
464-
trace, err = emulatedTreeToTrace(ctx, h.executor, h.storage, tree, emulator.FinalStates(), nil, h.configPool)
465-
if err != nil {
466-
return nil, toError(http.StatusInternalServerError, err)
468+
emulator, err := txemulator.NewTraceBuilder(options...)
469+
if err != nil {
470+
return nil, toError(http.StatusInternalServerError, err)
471+
}
472+
tree, err := emulator.Run(ctx, m)
473+
if err != nil {
474+
return nil, toProperEmulationError(err)
475+
}
476+
trace, err = emulatedTreeToTrace(ctx, h.executor, h.storage, tree, emulator.FinalStates(), nil, h.configPool)
477+
if err != nil {
478+
return nil, toError(http.StatusInternalServerError, err)
479+
}
480+
err = h.storage.SaveTraceWithState(hs, trace, []abi.MethodInvocation{}, 24*time.Hour)
481+
if err != nil {
482+
fmt.Println("not saved to scylla: ", err)
483+
}
467484
}
468485
}
469486
actions, err := bath.FindActions(ctx, trace, bath.WithInformationSource(h.storage))
@@ -489,34 +506,42 @@ func (h *Handler) EmulateMessageToTrace(ctx context.Context, request *oas.Emulat
489506
}
490507
trace, prs := h.mempoolEmulate.traces.Get(hash)
491508
if !prs {
492-
var m tlb.Message
493-
err = tlb.Unmarshal(c, &m)
494-
if err != nil {
495-
return nil, toError(http.StatusBadRequest, err)
496-
}
497-
configBase64, err := h.storage.TrimmedConfigBase64()
498-
if err != nil {
499-
return nil, toError(http.StatusInternalServerError, err)
500-
}
501-
options := []txemulator.TraceOption{
502-
txemulator.WithAccountsSource(h.storage),
503-
txemulator.WithConfigBase64(configBase64),
504-
}
505-
if !params.IgnoreSignatureCheck.Value {
506-
options = append(options, txemulator.WithSignatureCheck())
507-
}
509+
hs, err := c.HashString()
510+
trace, _, err = h.storage.GetTraceWithState(ctx, hs)
511+
if trace == nil {
512+
var m tlb.Message
513+
err = tlb.Unmarshal(c, &m)
514+
if err != nil {
515+
return nil, toError(http.StatusBadRequest, err)
516+
}
517+
configBase64, err := h.storage.TrimmedConfigBase64()
518+
if err != nil {
519+
return nil, toError(http.StatusInternalServerError, err)
520+
}
521+
options := []txemulator.TraceOption{
522+
txemulator.WithAccountsSource(h.storage),
523+
txemulator.WithConfigBase64(configBase64),
524+
}
525+
if !params.IgnoreSignatureCheck.Value {
526+
options = append(options, txemulator.WithSignatureCheck())
527+
}
508528

509-
emulator, err := txemulator.NewTraceBuilder(options...)
510-
if err != nil {
511-
return nil, toError(http.StatusInternalServerError, err)
512-
}
513-
tree, err := emulator.Run(ctx, m)
514-
if err != nil {
515-
return nil, toProperEmulationError(err)
516-
}
517-
trace, err = emulatedTreeToTrace(ctx, h.executor, h.storage, tree, emulator.FinalStates(), nil, h.configPool)
518-
if err != nil {
519-
return nil, toError(http.StatusInternalServerError, err)
529+
emulator, err := txemulator.NewTraceBuilder(options...)
530+
if err != nil {
531+
return nil, toError(http.StatusInternalServerError, err)
532+
}
533+
tree, err := emulator.Run(ctx, m)
534+
if err != nil {
535+
return nil, toProperEmulationError(err)
536+
}
537+
trace, err = emulatedTreeToTrace(ctx, h.executor, h.storage, tree, emulator.FinalStates(), nil, h.configPool)
538+
if err != nil {
539+
return nil, toError(http.StatusInternalServerError, err)
540+
}
541+
err = h.storage.SaveTraceWithState(hs, trace, []abi.MethodInvocation{}, 24*time.Hour)
542+
if err != nil {
543+
fmt.Println("not saved to scylla: ", err)
544+
}
520545
}
521546
}
522547
t := convertTrace(trace, h.addressBook)
@@ -603,44 +628,54 @@ func (h *Handler) EmulateMessageToWallet(ctx context.Context, request *oas.Emula
603628
if err != nil {
604629
return nil, toError(http.StatusInternalServerError, err)
605630
}
606-
configBase64, err := h.storage.TrimmedConfigBase64()
607-
if err != nil {
608-
return nil, toError(http.StatusInternalServerError, err)
609-
}
610631

611-
options := []txemulator.TraceOption{
612-
txemulator.WithConfigBase64(configBase64),
613-
txemulator.WithAccountsSource(h.storage),
614-
txemulator.WithLimit(1100),
615-
}
616-
accounts, err := convertEmulationParameters(request.Params)
617-
if err != nil {
618-
return nil, toError(http.StatusBadRequest, err)
619-
}
620-
var states []tlb.ShardAccount
621-
for accountID, balance := range accounts {
622-
originalState, err := h.storage.GetAccountState(ctx, accountID)
632+
hash, err := msgCell.HashString()
633+
trace, _, err := h.storage.GetTraceWithState(ctx, hash)
634+
if trace == nil {
635+
configBase64, err := h.storage.TrimmedConfigBase64()
636+
if err != nil {
637+
return nil, toError(http.StatusInternalServerError, err)
638+
}
639+
640+
options := []txemulator.TraceOption{
641+
txemulator.WithConfigBase64(configBase64),
642+
txemulator.WithAccountsSource(h.storage),
643+
txemulator.WithLimit(1100),
644+
}
645+
accounts, err := convertEmulationParameters(request.Params)
646+
if err != nil {
647+
return nil, toError(http.StatusBadRequest, err)
648+
}
649+
var states []tlb.ShardAccount
650+
for accountID, balance := range accounts {
651+
originalState, err := h.storage.GetAccountState(ctx, accountID)
652+
if err != nil {
653+
return nil, toError(http.StatusInternalServerError, err)
654+
}
655+
state, err := prepareAccountState(*walletAddress, originalState, balance)
656+
if err != nil {
657+
return nil, toError(http.StatusInternalServerError, err)
658+
}
659+
states = append(states, state)
660+
}
661+
662+
options = append(options, txemulator.WithAccounts(states...))
663+
emulator, err := txemulator.NewTraceBuilder(options...)
623664
if err != nil {
624665
return nil, toError(http.StatusInternalServerError, err)
625666
}
626-
state, err := prepareAccountState(*walletAddress, originalState, balance)
667+
tree, err := emulator.Run(ctx, m)
668+
if err != nil {
669+
return nil, toProperEmulationError(err)
670+
}
671+
trace, err = emulatedTreeToTrace(ctx, h.executor, h.storage, tree, emulator.FinalStates(), nil, h.configPool)
627672
if err != nil {
628673
return nil, toError(http.StatusInternalServerError, err)
629674
}
630-
states = append(states, state)
631-
}
632-
options = append(options, txemulator.WithAccounts(states...))
633-
emulator, err := txemulator.NewTraceBuilder(options...)
634-
if err != nil {
635-
return nil, toError(http.StatusInternalServerError, err)
636-
}
637-
tree, err := emulator.Run(ctx, m)
638-
if err != nil {
639-
return nil, toProperEmulationError(err)
640-
}
641-
trace, err := emulatedTreeToTrace(ctx, h.executor, h.storage, tree, emulator.FinalStates(), nil, h.configPool)
642-
if err != nil {
643-
return nil, toError(http.StatusInternalServerError, err)
675+
err = h.storage.SaveTraceWithState(hash, trace, []abi.MethodInvocation{}, 24*time.Hour)
676+
if err != nil {
677+
fmt.Println("not saved to scylla: ", err)
678+
}
644679
}
645680
t := convertTrace(trace, h.addressBook)
646681
actions, err := bath.FindActions(ctx, trace, bath.ForAccount(*walletAddress), bath.WithInformationSource(h.storage))

pkg/api/interfaces.go

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package api
33
import (
44
"context"
55
"crypto/ed25519"
6+
"time"
67

78
"github.com/tonkeeper/opentonapi/pkg/gasless"
89
"github.com/tonkeeper/opentonapi/pkg/oas"
@@ -111,6 +112,9 @@ type storage interface {
111112
GetAccountMultisigs(ctx context.Context, accountID ton.AccountID) ([]core.Multisig, error)
112113
GetMultisigByID(ctx context.Context, accountID ton.AccountID) (*core.Multisig, error)
113114

115+
SaveTraceWithState(msgHash string, trace *core.Trace, getMethods []abi.MethodInvocation, ttl time.Duration) error
116+
GetTraceWithState(ctx context.Context, msgHash string) (*core.Trace, []abi.MethodInvocation, error)
117+
114118
liteStorageRaw
115119
}
116120

pkg/core/trace.go

+54
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package core
22

33
import (
44
"context"
5+
"encoding/json"
56
"errors"
7+
"github.com/tonkeeper/tongo/ton"
68
"sync"
79

810
"github.com/shopspring/decimal"
@@ -65,6 +67,58 @@ func (t *Trace) SetAdditionalInfo(info *TraceAdditionalInfo) {
6567
t.additionalInfo = info
6668
}
6769

70+
func (t *TraceAdditionalInfo) MarshalJSON() ([]byte, error) {
71+
type Alias struct {
72+
JettonMasters map[string]string `json:",omitempty"`
73+
NftSaleContract *NftSaleContract `json:",omitempty"`
74+
STONfiPool *STONfiPool `json:",omitempty"`
75+
EmulatedTeleitemNFT *EmulatedTeleitemNFT `json:",omitempty"`
76+
}
77+
78+
masters := make(map[string]string)
79+
if t.JettonMasters != nil {
80+
for k, v := range t.JettonMasters {
81+
masters[k.String()] = v.String()
82+
}
83+
}
84+
85+
return json.Marshal(&Alias{
86+
JettonMasters: masters,
87+
NftSaleContract: t.NftSaleContract,
88+
STONfiPool: t.STONfiPool,
89+
EmulatedTeleitemNFT: t.EmulatedTeleitemNFT,
90+
})
91+
}
92+
93+
func (t *TraceAdditionalInfo) UnmarshalJSON(data []byte) error {
94+
type Alias struct {
95+
JettonMasters map[string]string `json:",omitempty"`
96+
NftSaleContract *NftSaleContract `json:",omitempty"`
97+
STONfiPool *STONfiPool `json:",omitempty"`
98+
EmulatedTeleitemNFT *EmulatedTeleitemNFT `json:",omitempty"`
99+
}
100+
101+
aux := &Alias{}
102+
if err := json.Unmarshal(data, aux); err != nil {
103+
return err
104+
}
105+
106+
if aux.JettonMasters != nil {
107+
t.JettonMasters = make(map[tongo.AccountID]tongo.AccountID)
108+
for kStr, vStr := range aux.JettonMasters {
109+
key := ton.MustParseAccountID(kStr)
110+
val := ton.MustParseAccountID(vStr)
111+
t.JettonMasters[key] = val
112+
}
113+
}
114+
115+
t.NftSaleContract = aux.NftSaleContract
116+
t.STONfiPool = aux.STONfiPool
117+
t.EmulatedTeleitemNFT = aux.EmulatedTeleitemNFT
118+
119+
return nil
120+
}
121+
68122
func (t *Trace) InProgress() bool {
69123
return t.countUncompleted() != 0
70124
}

0 commit comments

Comments
 (0)