From 52bf942757450fd47d32d4c8c366339effb39b05 Mon Sep 17 00:00:00 2001 From: Oleg Baranov Date: Wed, 6 Dec 2023 10:48:58 +0400 Subject: [PATCH] Fixed account proof check error on splitted shards --- example/wallet-cold-alike/main.go | 4 ++-- example/wallet/main.go | 3 ++- ton/block.go | 13 +++++++---- ton/block_test.go | 37 +++++++++++++++++++++++++++++++ ton/proof.go | 2 +- 5 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 ton/block_test.go diff --git a/example/wallet-cold-alike/main.go b/example/wallet-cold-alike/main.go index 865bf6b1..389f3198 100644 --- a/example/wallet-cold-alike/main.go +++ b/example/wallet-cold-alike/main.go @@ -51,7 +51,7 @@ func main() { if balance.Nano().Uint64() >= 3000000 { addr := address.MustParseAddr("EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N") - log.Println("sending transaction and waiting for confirmation...") + log.Println("sending transaction...") // default message ttl is 3 minutes, it is time during which you can send it to blockchain // if you need to set longer TTL, you could use this method @@ -82,7 +82,7 @@ func main() { return } - log.Println("transaction sent") + log.Println("transaction sent, we are not waiting for confirmation") return } diff --git a/example/wallet/main.go b/example/wallet/main.go index 55f80ed5..ccc4b4c6 100644 --- a/example/wallet/main.go +++ b/example/wallet/main.go @@ -68,7 +68,8 @@ func main() { log.Println("sending transaction and waiting for confirmation...") // if destination wallet is not initialized (or you don't care) - // you should set bounce to true to not get money back + // you should set bounce to false to not get money back. + // If bounce is true, money will be returned in case of not initialized destination wallet or smart-contract error bounce := false transfer, err := w.BuildTransfer(addr, tlb.MustFromTON("0.003"), bounce, "Hello from tonutils-go!") diff --git a/ton/block.go b/ton/block.go index 99da8f6a..80b88696 100644 --- a/ton/block.go +++ b/ton/block.go @@ -449,14 +449,14 @@ func (c *APIClient) GetBlockShardsInfo(ctx context.Context, master *BlockIDExt) } } - return LoadShardsFromHashes(inf.ShardHashes) + return LoadShardsFromHashes(inf.ShardHashes, false) case LSError: return nil, t } return nil, errUnexpectedResponse(resp) } -func LoadShardsFromHashes(shardHashes *cell.Dictionary) (shards []*BlockIDExt, err error) { +func LoadShardsFromHashes(shardHashes *cell.Dictionary, skipPruned bool) (shards []*BlockIDExt, err error) { if shardHashes == nil { return []*BlockIDExt{}, nil } @@ -473,12 +473,17 @@ func LoadShardsFromHashes(shardHashes *cell.Dictionary) (shards []*BlockIDExt, e } var binTree tlb.BinTree - err = binTree.LoadFromCell(binTreeRef) - if err != nil { + if err = tlb.LoadFromCellAsProof(&binTree, binTreeRef); err != nil { return nil, fmt.Errorf("load BinTree err: %w", err) } for _, bk := range binTree.All() { + if skipPruned && bk.Value.GetType() != cell.OrdinaryCellType { + // in case of split we have list with only needed shard, + // and pruned branch for others. + continue + } + loader := bk.Value.BeginParse() ab, err := loader.LoadUInt(4) diff --git a/ton/block_test.go b/ton/block_test.go new file mode 100644 index 00000000..cf34d15d --- /dev/null +++ b/ton/block_test.go @@ -0,0 +1,37 @@ +package ton + +import ( + "encoding/hex" + "github.com/xssnick/tonutils-go/tvm/cell" + "testing" +) + +func TestLoadShardsFromHashes(t *testing.T) { + data, err := hex.DecodeString("b5ee9c724102090100010b000103d040012201c002032201c00405284801012610bab489d8faa8c9dfaa65e8281895cfc66591881d1d5351574975ce386f2b00032201c00607284801013ca47d35fc14db1a5f2e33f74cf3e833974de0fea9f49759ea84d2522124d12b000201eb50134ea4181081ebe000013951e6cc660000013951e6cc6608c7a91c9653b122d1e49487ecc663e5bb59d8974d6ddd03a4c5cdd7c325498e92b103dc863224263143d3b59124e2a4bce36ddd4ce7f4c43ae0476430da34061280003e18b880000000000000001080fd6b2b80b3cecae02d12000000c90828480101c2256a5539b179d8831bcbfb692dc691ba4c604a72a60ff375306e2b29764a4900010013407735940203b9aca0202872d22f") + if err != nil { + t.Fatal(err) + } + + cl, err := cell.FromBOC(data) + if err != nil { + t.Fatal(err) + } + + di, err := cl.BeginParse().ToDict(32) + if err != nil { + t.Fatal(err) + } + + gotShards, err := LoadShardsFromHashes(di, true) + if err != nil { + t.Fatal(err) + } + if len(gotShards) != 1 { + t.Fatal("not 1 shard") + } + + gotShards, err = LoadShardsFromHashes(di, false) + if err == nil { + t.Fatal("should be err") + } +} diff --git a/ton/proof.go b/ton/proof.go index 21fab4c1..a5100fee 100644 --- a/ton/proof.go +++ b/ton/proof.go @@ -48,7 +48,7 @@ func CheckShardInMasterProof(master *BlockIDExt, shardProof []*cell.Cell, workch return fmt.Errorf("failed to check proof for mc state extra: %w", err) } - shards, err := LoadShardsFromHashes(stateExtra.ShardHashes) + shards, err := LoadShardsFromHashes(stateExtra.ShardHashes, true) if err != nil { return fmt.Errorf("failed to load shard hashes: %w", err) }