diff --git a/example/account-state/main.go b/example/account-state/main.go index 5d97dbff..9b04c288 100644 --- a/example/account-state/main.go +++ b/example/account-state/main.go @@ -38,10 +38,13 @@ func main() { return } - fmt.Printf("Status: %s\n", res.State.Status) - fmt.Printf("Balance: %s TON\n", res.State.Balance.TON()) - if res.Data != nil { - fmt.Printf("Data: %s\n", res.Data.Dump()) + fmt.Printf("Is active: %v\n", res.IsActive) + if res.IsActive { + fmt.Printf("Status: %s\n", res.State.Status) + fmt.Printf("Balance: %s TON\n", res.State.Balance.TON()) + if res.Data != nil { + fmt.Printf("Data: %s\n", res.Data.Dump()) + } } // take last tx info from account info diff --git a/tvm/cell/cell_test.go b/tvm/cell/cell_test.go index 5ccd23d2..2d700121 100644 --- a/tvm/cell/cell_test.go +++ b/tvm/cell/cell_test.go @@ -3,6 +3,7 @@ package cell import ( "bytes" "encoding/hex" + "math/big" "testing" ) @@ -15,6 +16,8 @@ func TestCell_Hash(t *testing.T) { b, _ := hex.DecodeString("bb2509fe3cff8f1faae19213774d218c018f9616cd397850c8ad9038db84eaa9") if !bytes.Equal(cc.Hash(), b) { + t.Log(hex.EncodeToString(cc.Hash())) + t.Log(hex.EncodeToString(b)) t.Fatal("hash diff") } } @@ -31,6 +34,22 @@ func TestBOC(t *testing.T) { boc := c.ToBOCWithFlags(false) if str != hex.EncodeToString(boc) { + t.Log(str) + t.Log(hex.EncodeToString(boc)) + t.Fatal("boc not same") + } +} + +func TestSmallBOC(t *testing.T) { + str := "b5ee9c72010101010002000000" + + c := BeginCell().EndCell() + + boc := c.ToBOCWithFlags(false) + + if str != hex.EncodeToString(boc) { + t.Log(str) + t.Log(hex.EncodeToString(boc)) t.Fatal("boc not same") } } @@ -50,3 +69,23 @@ func TestBOCWithCRC(t *testing.T) { t.Fatal("boc not same") } } + +func TestCell_Hash1(t *testing.T) { + emptyHash, _ := new(big.Int).SetString("68134197439415885698044414435951397869210496020759160419881882418413283430343", 10) + + if !bytes.Equal(BeginCell().EndCell().Hash(), emptyHash.Bytes()) { + t.Fatal("empty cell hash incorrect") + return + } + + refRef57bitsHash, _ := new(big.Int).SetString("111217512120054409408353636830563617100690868120902564345366655075146083288188", 10) + + if !bytes.Equal(BeginCell().MustStoreUInt(7, 5).MustStoreRef( + BeginCell().MustStoreRef( + BeginCell().MustStoreUInt(777777888, 57).EndCell(), + ).EndCell(), + ).EndCell().Hash(), refRef57bitsHash.Bytes()) { + t.Fatal("refRef57bits cell hash incorrect") + return + } +} diff --git a/tvm/cell/dict.go b/tvm/cell/dict.go index e6b900fe..47774476 100644 --- a/tvm/cell/dict.go +++ b/tvm/cell/dict.go @@ -8,6 +8,7 @@ import ( type Dictionary struct { storage map[string]*Cell + keySz int } type HashmapKV struct { @@ -18,6 +19,7 @@ type HashmapKV struct { func (c *LoadCell) LoadDict(keySz int) (*Dictionary, error) { d := Dictionary{ storage: map[string]*Cell{}, + keySz: keySz, } err := d.mapInner(keySz, keySz, c, BeginCell()) @@ -29,7 +31,12 @@ func (c *LoadCell) LoadDict(keySz int) (*Dictionary, error) { } func (d *Dictionary) Get(key *Cell) *Cell { - return d.storage[hex.EncodeToString(key.Hash())] + data, err := key.BeginParse().LoadSlice(d.keySz) + if err != nil { + return nil + } + + return d.storage[hex.EncodeToString(data)] } func (d *Dictionary) All() []HashmapKV { @@ -81,7 +88,7 @@ func (d *Dictionary) mapInner(keySz, leftKeySz int, loader *LoadCell, keyPrefix } // add node to map - d.storage[hex.EncodeToString(keyPrefix.EndCell().Hash())] = loader.MustToCell() + d.storage[hex.EncodeToString(keyPrefix.EndCell().BeginParse().MustLoadSlice(keySz))] = loader.MustToCell() return nil } diff --git a/tvm/cell/dict_test.go b/tvm/cell/dict_test.go index a7bf1f0d..ed81f251 100644 --- a/tvm/cell/dict_test.go +++ b/tvm/cell/dict_test.go @@ -1,9 +1,54 @@ package cell import ( + "encoding/hex" "testing" + + "github.com/xssnick/tonutils-go/address" ) func TestLoadCell_LoadDict(t *testing.T) { + boc, _ := hex.DecodeString("b5ee9c720102300100054b0003130104e5714b7720d7ecb8010203004801013e4b84df934ef609983108a9dd7592fa24bb91b54d6eedc6c326be7577a98317021503130101bdb4553ec71987b804050600480101b3e9649d10ccb379368e81a3a7e8e49c8eb53f6acc69b0ba2ffa80082f70ee3900010313010120755a2cbbd9dcf807080900480101ef083f99476ecb9c24950a511fb8ff0c0b615d36f8c92c1a62842cf6511f97ec002900480101bb06f3506745c5f6a6239d132a70b38439cb60ff95f62e45261ba12e844e889b0001031301007d799d984953f7b80a0b0c004801015cbe4962e258e4c54a77e143cab81187ce744039e80b695cf6b5e4ac6cdab0c5003000480101ec90a44eee02bed840c10e88351163ee9e3613eb9dbe8da760783da449714e2800010213010079cc055b5efbf1480d0e00480101605be65671091e8b17e64d728bfc23581bcde96b34c98f0fd20553ba5b5d064c002700480101aaed7ccc3904836f362ae06eb234b71d64e02eb4ba6d6b7869197a9ed5c4b0b800010213010046bd7f899035d1680f10004801010aed90d8b02fead606c94c7f3dc69c41657ea1e3dac66d2e663de2ef5dc45dc700250213010030e8b0869ec848081112004801016ab17b36ac385cd82a04071b8cbf7fe115a7eec4f3c8025f3e3c6be947e1450a0022004801011efcebeedc52ed504841f138a8a2b1a0b34d9450601abdfa74fd6a339968da480023021301002d0b36c670d5d5a8131400480101f803f2d58880207f22895e7ce98dbfc86a8a9f3b3eda2435daa14f4edd40b2b4001a021100fe6160ec7cc2dfc81516004801015d50cb57162ef4620be7b08f414d2ebfe15a465f218a6ef3a18e9771d31969ba001d021100fd83ac455e5d08a8171800480101d0b09addaa1a7d59f89bf793d2be0492fcde2aa67f2822fa2b0039c8fc4cf1d9001c021100fd81fcf831e7ec48191a021100fd814c0d292318e81b1c00480101dab7229c497785a582980a4a7510de0d7d9e85532eb276607fb6a206cfd849b600150048010196abdc5299b1882c8bddd82233dd3e2e23872ece8b6086393e383ed94b5195450014021100fd808ec22cab74e81d1e00480101d6bfa8852433a63a2e778bacd3aea4976001a497e8babc04f9cc29d506850d4f0011021100fd808254f4c4bf881f200048010121e4f3117fc65aa920ba080dc42c23f1daa95b3cf9a29e2eab0ad597d95141bf000f021100fd8079e9fa43d2a82122004801010c3ca3e169e651ab7b7839f3629cd3f4cad961b3c6dacc549f2df2070df5bca0000f021100fd8076edcbc1c688232400480101de48ed3d3c0cc949b8840ee4f7362632824e54b67b0350ba186da4f116dd8c84000c021100fd8074a2fa301f48252600480101d55d236bd3e2e12623ba6ffce9c99ad779b500768c6dae25fe0b9a8f4f387615000e021100fd807499d393e72827280048010160f1f53a819b9663e6cf4a7f2ad05f14473c1040cf8625144a425db0e3d1fbe10001021100fd80748bc9bea1e8292a0211503f601d1981cd9bc22b2c00480101f9c11528dca951adb47dc69355d17db4c654228a5be577e8ddb735bb9a13fb3900010212680fd8074638b7c7b22d2e0048010177ff19c4fb2cfde80e90b294436e2f201c83815704e37a47ca8b9e946b31a149000900480101562e0d4cdb2a66946e9c9317fbb0be0d737932bf0cad82b3684e818fc04df12e0009019dba14b98dca6d1cbf2f323117af319a45c09562da3b1d49f86e900e83cc6a00fd8068c4a3f3948b1b13c730604edab03c6442a9101f9f1380eb4af3db3463099c2148798816bf2000019e55d81e8c682f004801011c3e74fed2d4c20c35c2953eb1981e75b79018d4da774f38f6f65f13962088d30001") + c, err := FromBOC(boc) + if err != nil { + t.Fatal(err) + return + } + + dict, err := c.BeginParse().LoadDict(256) + if err != nil { + t.Fatal(err) + return + } + + addr := address.MustParseAddr("EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N") + data := dict.Get(BeginCell().MustStoreSlice(addr.Data(), 256).EndCell()) + if data == nil { + t.Fatal("not in dict") + return + } + + data = dict.Get(BeginCell().MustStoreSlice(addr.Data(), 32).EndCell()) + if data != nil { + t.Fatal("in dict") + return + } + + addr2 := address.MustParseAddr("kQB3P0cDOtkFDdxB77YX-F2DGkrIszmZkmyauMnsP1gg0inM") + data = dict.Get(BeginCell().MustStoreSlice(addr2.Data(), 256).EndCell()) + if data != nil { + t.Fatal("in dict") + return + } + + all := dict.All() + if len(all) != 1 { + t.Fatal("keys num != 1") + return + } + if all[0].Key != hex.EncodeToString(addr.Data()) { + t.Fatal("key in all not correct") + return + } } diff --git a/tvm/cell/load_test.go b/tvm/cell/load_test.go new file mode 100644 index 00000000..54a5d3d5 --- /dev/null +++ b/tvm/cell/load_test.go @@ -0,0 +1,25 @@ +package cell + +import ( + "testing" + + "github.com/xssnick/tonutils-go/address" +) + +func TestLoadCell_LoadAddr(t *testing.T) { + addr := address.MustParseAddr("EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N") + + c := BeginCell().MustStoreUInt(1, 3).MustStoreAddr(addr).EndCell().BeginParse() + c.MustLoadUInt(3) + + lAddr, err := c.LoadAddr() + if err != nil { + t.Fatal(err) + return + } + + if addr.String() != lAddr.String() { + t.Fatal(err) + return + } +} diff --git a/tvm/cell/parse.go b/tvm/cell/parse.go index 6849ea37..3a5dca1f 100644 --- a/tvm/cell/parse.go +++ b/tvm/cell/parse.go @@ -59,9 +59,7 @@ func FromBOCMultiRoot(data []byte) ([]Cell, error) { rootList := r.MustReadBytes(rootsNum * cellNumSizeBytes) // root_list:(roots * ##(size * 8)) rootIndex := dynInt(rootList[0:cellNumSizeBytes]) - if rootIndex != 0 { - // return nil, fmt.Errorf("first root index should be 0, but it is %d", rootIndex) - } + _ = rootIndex payload, err := r.ReadBytes(dataLen) if err != nil { diff --git a/tvm/cell/serialize.go b/tvm/cell/serialize.go index 4e0aa884..a8d3e3f8 100644 --- a/tvm/cell/serialize.go +++ b/tvm/cell/serialize.go @@ -24,7 +24,7 @@ func (c *Cell) ToBOCWithFlags(withCRC bool) []byte { orderCells := flattenIndex([]*Cell{c}) // bytes needed to store num of cells - cellSizeBits := math.Log2(float64(len(orderCells))) + cellSizeBits := math.Log2(float64(len(orderCells)) + 1) cellSizeBytes := byte(math.Ceil(cellSizeBits / 8)) var payload []byte @@ -34,7 +34,7 @@ func (c *Cell) ToBOCWithFlags(withCRC bool) []byte { } // bytes needed to store len of payload - sizeBits := math.Log2(float64(len(payload))) + sizeBits := math.Log2(float64(len(payload)) + 1) sizeBytes := byte(math.Ceil(sizeBits / 8)) // has_idx 1bit, hash_crc32 1bit, has_cache_bits 1bit, flags 2bit, size_bytes 3 bit