Skip to content

Commit a3868e2

Browse files
committed
Dynamic msg TL-B - JSON decoding
1 parent 8d0e96d commit a3868e2

File tree

5 files changed

+70
-154
lines changed

5 files changed

+70
-154
lines changed

pkg/ton/debug/decoders/ccip/ccipsendexecutor/ccipsendexecutor.go

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package ccipsendexecutor
22

33
import (
44
"github.com/xssnick/tonutils-go/address"
5-
"github.com/xssnick/tonutils-go/tlb"
65
"github.com/xssnick/tonutils-go/tvm/cell"
76

87
cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment"
@@ -13,6 +12,14 @@ import (
1312
"github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm"
1413
)
1514

15+
// TODO: auto-generate this map from a set of msgs using TL-B tag to read opcodes
16+
var TLBs = map[int]interface{}{
17+
ccipsendexecutor.OpcodeCCIPSendExecutorExecute: ccipsendexecutor.Execute{},
18+
19+
// Note: We don't handle JettonTransferNotification or FeeQuoter_MessageValidated here
20+
// because they are already handled by their respective decoders (jetton wallet and fee quoter)
21+
}
22+
1623
type decoder struct {
1724
payloadDecoders map[cldf.ContractType]lib.ContractDecoder
1825
}
@@ -38,26 +45,7 @@ func (d *decoder) ExternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) {
3845

3946
// InternalMessageInfo implements lib.ContractDecoder.
4047
func (d *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) {
41-
r := msg.BeginParse()
42-
if r.BitsLeft() == 0 {
43-
return nil, &lib.UnknownMessageError{}
44-
}
45-
opCode, err := r.PreloadUInt(32)
46-
if err != nil {
47-
return nil, err
48-
}
49-
if opCode == ccipsendexecutor.OpcodeCCIPSendExecutorExecute {
50-
var execute ccipsendexecutor.Execute
51-
err := tlb.LoadFromCell(&execute, r)
52-
if err != nil {
53-
return nil, err
54-
}
55-
return lib.NewMessageInfo("CCIPSendExecutorExecute", execute)
56-
}
57-
58-
// Note: We don't handle JettonTransferNotification or FeeQuoter_MessageValidated here
59-
// because they are already handled by their respective decoders (jetton wallet and fee quoter)
60-
return nil, &lib.UnknownMessageError{}
48+
return lib.NewMessageInfoFromCell(d.ContractType(), msg, TLBs)
6149
}
6250

6351
func (d *decoder) ExitCodeInfo(exitCode tvm.ExitCode) (string, error) {

pkg/ton/debug/decoders/ccip/feequoter/feequoter.go

Lines changed: 11 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package feequoter
22

33
import (
44
"github.com/xssnick/tonutils-go/address"
5-
"github.com/xssnick/tonutils-go/tlb"
65
"github.com/xssnick/tonutils-go/tvm/cell"
76

87
cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment"
@@ -13,6 +12,16 @@ import (
1312
"github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm"
1413
)
1514

15+
// TODO: auto-generate this map from a set of msgs using TL-B tag to read opcodes
16+
var TLBs = map[int]interface{}{
17+
feequoter.OpcodeUpdatePrices: feequoter.UpdatePrices{},
18+
feequoter.OpcodeUpdateFeeTokens: feequoter.UpdateFeeTokens{},
19+
feequoter.OpcodeUpdateTokenTransferFeeConfigs: feequoter.UpdateTokenTransferFeeConfigs{},
20+
feequoter.OpcodeUpdateDestChainConfigs: feequoter.UpdateDestChainConfigs{},
21+
feequoter.OpcodeFeeQuoterGetValidatedFee: feequoter.GetValidatedFee{},
22+
feequoter.OpcodeFeeQuoterMessageValidated: feequoter.MessageValidated{},
23+
}
24+
1625
type decoder struct {
1726
}
1827

@@ -37,59 +46,7 @@ func (d *decoder) ExternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) {
3746

3847
// InternalMessageInfo implements lib.ContractDecoder.
3948
func (d *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) {
40-
r := msg.BeginParse()
41-
if r.BitsLeft() == 0 {
42-
return nil, &lib.UnknownMessageError{}
43-
}
44-
opCode, err := r.PreloadUInt(32)
45-
if err != nil {
46-
return nil, err
47-
}
48-
switch opCode {
49-
case feequoter.OpcodeUpdatePrices:
50-
var updatePrices feequoter.UpdatePrices
51-
err := tlb.LoadFromCell(&updatePrices, r)
52-
if err != nil {
53-
return nil, err
54-
}
55-
return lib.NewMessageInfo("UpdatePrices", updatePrices)
56-
case feequoter.OpcodeUpdateFeeTokens:
57-
var updateFeeTokens feequoter.UpdateFeeTokens
58-
err := tlb.LoadFromCell(&updateFeeTokens, r)
59-
if err != nil {
60-
return nil, err
61-
}
62-
return lib.NewMessageInfo("UpdateFeeTokens", updateFeeTokens)
63-
case feequoter.OpcodeUpdateTokenTransferFeeConfigs:
64-
var updateConfigs feequoter.UpdateTokenTransferFeeConfigs
65-
err := tlb.LoadFromCell(&updateConfigs, r)
66-
if err != nil {
67-
return nil, err
68-
}
69-
return lib.NewMessageInfo("UpdateTokenTransferFeeConfigs", updateConfigs)
70-
case feequoter.OpcodeUpdateDestChainConfigs:
71-
var updateDestConfigs feequoter.UpdateDestChainConfigs
72-
err := tlb.LoadFromCell(&updateDestConfigs, r)
73-
if err != nil {
74-
return nil, err
75-
}
76-
return lib.NewMessageInfo("UpdateDestChainConfigs", updateDestConfigs)
77-
case feequoter.OpcodeFeeQuoterGetValidatedFee:
78-
var getValidatedFee feequoter.GetValidatedFee
79-
err := tlb.LoadFromCell(&getValidatedFee, r)
80-
if err != nil {
81-
return nil, err
82-
}
83-
return lib.NewMessageInfo("GetValidatedFee", getValidatedFee)
84-
case feequoter.OpcodeFeeQuoterMessageValidated:
85-
var messageValidated feequoter.MessageValidated
86-
err := tlb.LoadFromCell(&messageValidated, r)
87-
if err != nil {
88-
return nil, err
89-
}
90-
return lib.NewMessageInfo("MessageValidated", messageValidated)
91-
}
92-
return nil, &lib.UnknownMessageError{}
49+
return lib.NewMessageInfoFromCell(d.ContractType(), msg, TLBs)
9350
}
9451

9552
func (d *decoder) ExitCodeInfo(exitCode tvm.ExitCode) (string, error) {

pkg/ton/debug/decoders/ccip/onramp/onramp.go

Lines changed: 11 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,16 @@ import (
1515
"github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm"
1616
)
1717

18+
// TODO: auto-generate this map from a set of msgs using TL-B tag to read opcodes
19+
var TLBs = map[int]interface{}{
20+
onramp.OpcodeOnRampSend: onramp.Send{},
21+
onramp.OpcodeOnRampWithdrawJettons: onramp.WithdrawJettons{},
22+
onramp.OpcodeOnRampExecutorFinishedSuccessfully: onramp.ExecutorFinishedSuccessfully{},
23+
onramp.OpcodeSetDynamicConfig: onramp.SetDynamicConfigMessage{},
24+
onramp.OpcodeUpdateDestChainConfigs: onramp.UpdateDestChainConfigsMessage{},
25+
onramp.OpcodeUpdateAllowlists: onramp.UpdateAllowlistsMessage{},
26+
}
27+
1828
type decoder struct {
1929
payloadDecoders map[cldf.ContractType]lib.ContractDecoder
2030
}
@@ -54,59 +64,7 @@ func (d *decoder) ExternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) {
5464

5565
// InternalMessageInfo implements lib.ContractDecoder.
5666
func (d *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) {
57-
r := msg.BeginParse()
58-
if r.BitsLeft() == 0 {
59-
return nil, &lib.UnknownMessageError{}
60-
}
61-
opCode, err := r.PreloadUInt(32)
62-
if err != nil {
63-
return nil, err
64-
}
65-
switch opCode {
66-
case onramp.OpcodeOnRampSend:
67-
var onRampSend onramp.Send
68-
err := tlb.LoadFromCell(&onRampSend, r)
69-
if err != nil {
70-
return nil, err
71-
}
72-
return lib.NewMessageInfo("OnRampSend", onRampSend)
73-
case onramp.OpcodeOnRampWithdrawJettons:
74-
var withdrawJettons onramp.WithdrawJettons
75-
err := tlb.LoadFromCell(&withdrawJettons, r)
76-
if err != nil {
77-
return nil, err
78-
}
79-
return lib.NewMessageInfo("WithdrawJettons", withdrawJettons)
80-
case onramp.OpcodeOnRampExecutorFinishedSuccessfully:
81-
var executorFinished onramp.ExecutorFinishedSuccessfully
82-
err := tlb.LoadFromCell(&executorFinished, r)
83-
if err != nil {
84-
return nil, err
85-
}
86-
return lib.NewMessageInfo("ExecutorFinishedSuccessfully", executorFinished)
87-
case onramp.OpcodeSetDynamicConfig:
88-
var setDynamicConfig onramp.SetDynamicConfigMessage
89-
err := tlb.LoadFromCell(&setDynamicConfig, r)
90-
if err != nil {
91-
return nil, err
92-
}
93-
return lib.NewMessageInfo("SetDynamicConfig", setDynamicConfig)
94-
case onramp.OpcodeUpdateDestChainConfigs:
95-
var updateDestChainConfigs onramp.UpdateDestChainConfigsMessage
96-
err := tlb.LoadFromCell(&updateDestChainConfigs, r)
97-
if err != nil {
98-
return nil, err
99-
}
100-
return lib.NewMessageInfo("UpdateDestChainConfigs", updateDestChainConfigs)
101-
case onramp.OpcodeUpdateAllowlists:
102-
var updateAllowlists onramp.UpdateAllowlistsMessage
103-
err := tlb.LoadFromCell(&updateAllowlists, r)
104-
if err != nil {
105-
return nil, err
106-
}
107-
return lib.NewMessageInfo("UpdateAllowlists", updateAllowlists)
108-
}
109-
return nil, &lib.UnknownMessageError{}
67+
return lib.NewMessageInfoFromCell(d.ContractType(), msg, TLBs)
11068
}
11169

11270
func (d *decoder) ExitCodeInfo(exitCode tvm.ExitCode) (string, error) {

pkg/ton/debug/decoders/ccip/router/router.go

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package router
22

33
import (
44
"github.com/xssnick/tonutils-go/address"
5-
"github.com/xssnick/tonutils-go/tlb"
65
"github.com/xssnick/tonutils-go/tvm/cell"
76

87
cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment"
@@ -13,6 +12,12 @@ import (
1312
"github.com/smartcontractkit/chainlink-ton/pkg/ton/tvm"
1413
)
1514

15+
// TODO: auto-generate this map from a set of msgs using TL-B tag to read opcodes
16+
var TLBs = map[int]interface{}{
17+
router.OpcodeSetRamps: router.SetRamps{},
18+
router.OpcodeCCIPSend: router.CCIPSend{},
19+
}
20+
1621
type decoder struct {
1722
payloadDecoders map[cldf.ContractType]lib.ContractDecoder
1823
}
@@ -38,31 +43,7 @@ func (d *decoder) ExternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) {
3843

3944
// InternalMessageInfo implements lib.ContractDecoder.
4045
func (d *decoder) InternalMessageInfo(msg *cell.Cell) (lib.MessageInfo, error) {
41-
r := msg.BeginParse()
42-
if r.BitsLeft() == 0 {
43-
return nil, &lib.UnknownMessageError{}
44-
}
45-
opCode, err := r.PreloadUInt(32)
46-
if err != nil {
47-
return nil, err
48-
}
49-
switch opCode {
50-
case router.OpcodeSetRamps:
51-
var setRamps router.SetRamps
52-
err := tlb.LoadFromCell(&setRamps, r)
53-
if err != nil {
54-
return nil, err
55-
}
56-
return lib.NewMessageInfo("SetRamps", setRamps)
57-
case router.OpcodeCCIPSend:
58-
var ccipSend router.CCIPSend
59-
err := tlb.LoadFromCell(&ccipSend, r)
60-
if err != nil {
61-
return nil, err
62-
}
63-
return lib.NewMessageInfo("CCIPSend", ccipSend)
64-
}
65-
return nil, &lib.UnknownMessageError{}
46+
return lib.NewMessageInfoFromCell(d.ContractType(), msg, TLBs)
6647
}
6748

6849
func (d *decoder) ExitCodeInfo(exitCode tvm.ExitCode) (string, error) {

pkg/ton/debug/lib/lib.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ package lib
22

33
import (
44
"encoding/json"
5+
"fmt"
6+
"reflect"
57

68
"github.com/xssnick/tonutils-go/address"
9+
"github.com/xssnick/tonutils-go/tlb"
710
"github.com/xssnick/tonutils-go/tvm/cell"
811

912
cldf "github.com/smartcontractkit/chainlink-deployments-framework/deployment"
@@ -64,6 +67,35 @@ func NewMessageInfo[T any](name string, msg T) (MessageInfo, error) {
6467
}, nil
6568
}
6669

70+
// NewMessageInfoFromCell attempts to decode the given cell using the provided TL-B candidates mapped by their opcodes.
71+
func NewMessageInfoFromCell(t cldf.ContractType, msg *cell.Cell, tlbs map[int]interface{}) (MessageInfo, error) {
72+
r := msg.BeginParse()
73+
if r.BitsLeft() == 0 {
74+
return nil, &UnknownMessageError{}
75+
}
76+
opCode, err := r.PreloadUInt(32)
77+
if err != nil {
78+
return nil, fmt.Errorf("failed to preload opcode: %w", err)
79+
}
80+
81+
i, ok := tlbs[int(opCode)]
82+
if !ok {
83+
return nil, &UnknownMessageError{}
84+
}
85+
86+
// create new instance of the candidate type
87+
rt := reflect.TypeOf(i)
88+
inst := reflect.New(rt).Interface() // pointer to zero value
89+
90+
// attempt decode - replace tlb.FromCell with the actual decode API you have
91+
if err := tlb.LoadFromCell(inst, r); err != nil {
92+
return nil, fmt.Errorf("failed to decode OnRamp message for opcode 0x%X: %w", opCode, err)
93+
}
94+
95+
name := fmt.Sprintf("%s/%s", t, rt.Name())
96+
return NewMessageInfo(name, inst)
97+
}
98+
6799
type messageInfo struct {
68100
name string
69101
short string

0 commit comments

Comments
 (0)