Skip to content

Commit

Permalink
Merge pull request #177 from xssnick/dev-v19
Browse files Browse the repository at this point in the history
Added support for new LS proof scheme of GetBlockShardsInfo
  • Loading branch information
xssnick authored Mar 21, 2024
2 parents 5501189 + bd70e19 commit f8773e4
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 21 deletions.
3 changes: 3 additions & 0 deletions example/block-scan/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ func getNotSeenShards(ctx context.Context, api ton.APIClientWrapped, shard *ton.
return ret, nil
}

// FYI: You can find more advanced, optimized and parallelized block scanner in payment network implementation:
// https://github.com/xssnick/ton-payment-network/blob/master/tonpayments/chain/block-scan.go

func main() {
client := liteclient.NewConnectionPool()

Expand Down
4 changes: 2 additions & 2 deletions tl/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ func serializeField(tags []string, value reflect.Value) (buf []byte, err error)
} else if value.Type() == cellArrType {
cells := value.Interface().([]*cell.Cell)
if num > 0 && num != len(cells) {
return nil, fmt.Errorf("incorrect cells len in field %s", value.Type().String())
return nil, fmt.Errorf("incorrect cells len %d in field %s", len(cells), value.Type().String())
}
return ToBytes(cell.ToBOCWithFlags(cells, false)), nil
}
Expand Down Expand Up @@ -528,7 +528,7 @@ func parseField(data []byte, tags []string, value *reflect.Value) (_ []byte, err
return data, nil
} else if value.Type() == cellArrType {
if num > 0 && num != len(cells) {
return nil, fmt.Errorf("incorrect cells len in field %s", value.Type().String())
return nil, fmt.Errorf("incorrect cells len %d in field %s", len(cells), value.Type().String())
}
value.Set(reflect.ValueOf(cells))
return data, nil
Expand Down
54 changes: 36 additions & 18 deletions ton/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ type ZeroStateIDExt struct {

type AllShardsInfo struct {
ID *BlockIDExt `tl:"struct"`
Proof []*cell.Cell `tl:"cell 2"`
Proof []*cell.Cell `tl:"cell"`
Data *cell.Cell `tl:"cell"`
}

Expand Down Expand Up @@ -524,28 +524,46 @@ func (c *APIClient) GetBlockShardsInfo(ctx context.Context, master *BlockIDExt)
}

if c.proofCheckPolicy != ProofCheckPolicyUnsafe {
shardState, err := CheckBlockShardStateProof(t.Proof, master.RootHash)
if err != nil {
return nil, fmt.Errorf("failed to check proof: %w", err)
if len(t.Proof) == 0 {
return nil, fmt.Errorf("empty proof")
}

mcShort := shardState.McStateExtra.BeginParse()
if v, err := mcShort.LoadUInt(16); err != nil || v != 0xcc26 {
return nil, fmt.Errorf("invalic mc extra in proof")
}
switch len(t.Proof) {
case 1:
blockProof, err := CheckBlockProof(t.Proof[0], master.RootHash)
if err != nil {
return nil, fmt.Errorf("failed to check proof: %w", err)
}

dictProof, err := mcShort.LoadMaybeRef()
if err != nil {
return nil, fmt.Errorf("failed to load dict proof: %w", err)
}
if blockProof.Extra == nil || blockProof.Extra.Custom == nil || !bytes.Equal(blockProof.Extra.Custom.ShardHashes.AsCell().Hash(0), t.Data.MustPeekRef(0).Hash()) {
return nil, fmt.Errorf("incorrect proof")
}
case 2: // old LS compatibility
shardState, err := CheckBlockShardStateProof(t.Proof, master.RootHash)
if err != nil {
return nil, fmt.Errorf("failed to check proof: %w", err)
}

if dictProof == nil && inf.ShardHashes.IsEmpty() {
return []*BlockIDExt{}, nil
}
mcShort := shardState.McStateExtra.BeginParse()
if v, err := mcShort.LoadUInt(16); err != nil || v != 0xcc26 {
return nil, fmt.Errorf("invalic mc extra in proof")
}

dictProof, err := mcShort.LoadMaybeRef()
if err != nil {
return nil, fmt.Errorf("failed to load dict proof: %w", err)
}

if (dictProof == nil) != inf.ShardHashes.IsEmpty() ||
!bytes.Equal(dictProof.MustToCell().Hash(0), t.Data.MustPeekRef(0).Hash()) {
return nil, fmt.Errorf("incorrect proof")
if dictProof == nil && inf.ShardHashes.IsEmpty() {
return []*BlockIDExt{}, nil
}

if (dictProof == nil) != inf.ShardHashes.IsEmpty() ||
!bytes.Equal(dictProof.MustToCell().Hash(0), t.Data.MustPeekRef(0).Hash()) {
return nil, fmt.Errorf("incorrect proof")
}
default:
return nil, fmt.Errorf("incorrect proof roots num")
}
}

Expand Down
6 changes: 6 additions & 0 deletions ton/jetton/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ func TestJettonMasterClient_Transfer(t *testing.T) {
panic(err)
}

// wait next block to be sure everything updated
block, err = api.WaitForBlock(block.SeqNo + 7).GetMasterchainInfo(ctx)
if err != nil {
t.Fatal("Wait master err:", err.Error())
}

b2, err := tokenWallet.GetBalanceAtBlock(ctx, block)
if err != nil {
t.Fatal(err)
Expand Down
6 changes: 6 additions & 0 deletions ton/nft/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@ func Test_NftMintTransfer(t *testing.T) {
t.Fatal("Send err:", err.Error())
}

// wait next block to be sure everything updated
block, err = api.WaitForBlock(block.SeqNo + 7).GetMasterchainInfo(ctx)
if err != nil {
t.Fatal("Wait master err:", err.Error())
}

newData, err := nft.GetNFTDataAtBlock(ctx, block)
if err != nil {
t.Fatal("GetNFTData err:", err.Error())
Expand Down
5 changes: 5 additions & 0 deletions ton/payments/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ func TestClient_DeployAsyncChannel(t *testing.T) {
t.Fatal(fmt.Errorf("failed to deploy channel: %w", err))
}

block, err = client.api.WaitForBlock(block.SeqNo + 7).GetMasterchainInfo(context.Background())
if err != nil {
t.Fatal(fmt.Errorf("failed to wait block: %w", err))
}

ch, err := client.GetAsyncChannel(context.Background(), block, channelAddr, true)
if err != nil {
t.Fatal(fmt.Errorf("failed to get channel: %w", err))
Expand Down
8 changes: 7 additions & 1 deletion ton/wallet/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,13 @@ func TestWallet_DeployContract(t *testing.T) {
}
t.Logf("contract address: %s", addr.String())

res, err := api.RunGetMethod(ctx, block, addr, "dappka", 5, 10)
// wait next block to be sure everything updated
block, err = api.WaitForBlock(block.SeqNo + 5).GetMasterchainInfo(ctx)
if err != nil {
t.Fatal("wait master err:", err.Error())
}

res, err := api.WaitForBlock(block.SeqNo).RunGetMethod(ctx, block, addr, "dappka", 5, 10)
if err != nil {
t.Fatal("run err:", err)
}
Expand Down

0 comments on commit f8773e4

Please sign in to comment.