Skip to content

Commit

Permalink
txemulator.Emulate() to support libraries
Browse files Browse the repository at this point in the history
  • Loading branch information
aleksej-paschenko committed Jul 21, 2023
1 parent 39c7597 commit 0fc8b68
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 398 deletions.
41 changes: 41 additions & 0 deletions txemulator/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type TraceOptions struct {

type accountGetter interface {
GetAccountState(ctx context.Context, a tongo.AccountID) (tlb.ShardAccount, error)
GetLibraries(ctx context.Context, libraries []tongo.Bits256) (map[tongo.Bits256]*boc.Cell, error)
}

func WithConfig(c *boc.Cell) TraceOption {
Expand Down Expand Up @@ -143,6 +144,7 @@ func NewTraceBuilder(options ...TraceOption) (*Tracer, error) {
if err != nil {
return nil, err
}
// TODO: set gas limit, currently, the transaction emulator doesn't support that
return &Tracer{
e: e,
currentShardAccount: option.predefinedAccounts,
Expand All @@ -151,6 +153,21 @@ func NewTraceBuilder(options ...TraceOption) (*Tracer, error) {
}, nil
}

func accountCode(account tlb.ShardAccount) *boc.Cell {
if account.Account.SumType == "AccountNone" {
return nil
}
if account.Account.Account.Storage.State.SumType != "AccountActive" {
return nil
}
code := account.Account.Account.Storage.State.AccountActive.StateInit.Code
if !code.Exists {
return nil
}
cell := code.Value.Value
return &cell
}

func (t *Tracer) Run(ctx context.Context, message tlb.Message) (*TxTree, error) {
if t.counter >= t.limit {
return nil, fmt.Errorf("to many iterations: %v/%v", t.counter, t.limit)
Expand Down Expand Up @@ -178,6 +195,30 @@ func (t *Tracer) Run(ctx context.Context, message tlb.Message) (*TxTree, error)
return nil, err
}
}
var publicLibs map[tongo.Bits256]*boc.Cell
if code := accountCode(state); code != nil {
hashes, err := FindLibraries(code)
if err != nil {
return nil, err
}
if len(hashes) > 0 {
libs, err := t.blockchain.GetLibraries(ctx, hashes)
if err != nil {
return nil, err
}
publicLibs = libs
}
}
if len(publicLibs) > 0 {
libsBoc, err := LibrariesToBase64(publicLibs)
if err != nil {
return nil, err
}
if err := t.e.setLibs(libsBoc); err != nil {
return nil, err
}
}
// TODO: look up libraries in the msg's stateInit, so if it's a deploy contract message, Emulate() won't fail.
result, err := t.e.Emulate(state, message)
if err != nil {
return nil, err
Expand Down
37 changes: 36 additions & 1 deletion txemulator/trace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ package txemulator

import (
"context"
"testing"

"github.com/tonkeeper/tongo"
"github.com/tonkeeper/tongo/boc"
"github.com/tonkeeper/tongo/liteapi"
"github.com/tonkeeper/tongo/tlb"
"github.com/tonkeeper/tongo/wallet"
"testing"
)

const SEED = "way label strategy scheme park virtual walnut illegal fringe once state defense museum bone satoshi feel diary buddy notice solve moral maple video local"
Expand Down Expand Up @@ -61,3 +62,37 @@ func TestSimpleEmulation(t *testing.T) {
t.Fatal("invalid amount")
}
}

func TestEmulate(t *testing.T) {
// this message is for "EQBAF7OBsy_1R8Zs33l6XMP3k1OyMv6Nv-b_-n-qf7de9qp2", which uses a public library.
c, err := boc.DeserializeSinglRootBase64("te6ccgEBAgEAoAABz4gAgC9nA2Zf6o+M2b7y9LmH7yanZGX9G3/N//T/VP9uvewComZfYno/fswnemt9B6xfHWRtZ2vKvL8C7ZiExKR3s3vsDDRnpxb5Oaoi7ATNea26glvtLlEwEFRoyIL2ZgqIaAAAAAgcAQBmYgA2ZpktQsYby0n9cV5VWOFINBjScIU2HdondFsK3lDpEBzEtAAAAAAAAAAAAAAAAAAA")
if err != nil {
t.Fatal(err)
}
var m tlb.Message
if err = tlb.Unmarshal(c, &m); err != nil {
t.Fatal(err)
}
client, err := liteapi.NewClient(liteapi.Mainnet(), liteapi.FromEnvs())
if err != nil {
t.Fatal(err)
}
emulator, err := NewTraceBuilder(WithAccountsSource(client))
if err != nil {
t.Fatalf("NewTraceBuilder() failed: %v", err)
}
tree, err := emulator.Run(context.Background(), m)
if err != nil {
t.Fatalf("Run() failed: %v", err)
}
if !tree.TX.IsSuccess() {
t.Fatalf("tx failed")
}
if len(tree.Children) != 1 {
t.Fatalf("expected tx to has 1 child")
}
second := tree.Children[0].TX
if !second.IsSuccess() {
t.Fatalf("second tx failed")
}
}
4 changes: 4 additions & 0 deletions txemulator/txemulator.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,10 @@ func (e *Emulator) SetLibs(libs *boc.Cell) error {
if err != nil {
return err
}
return e.setLibs(libsBoc)
}

func (e *Emulator) setLibs(libsBoc string) error {
cLibsStr := C.CString(libsBoc)
defer C.free(unsafe.Pointer(cLibsStr))
ok := C.transaction_emulator_set_libs(e.emulator, cLibsStr)
Expand Down
Loading

0 comments on commit 0fc8b68

Please sign in to comment.