Skip to content

Commit

Permalink
Add tongo.ParseTlbMessage() and change some funcs to accept tlb.Message
Browse files Browse the repository at this point in the history
  • Loading branch information
aleksej-paschenko committed Dec 15, 2023
1 parent ac3b4ac commit 9c6ebb4
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 15 deletions.
12 changes: 10 additions & 2 deletions liteapi/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ func VerifySendMessagePayload(payload []byte) error {
return err
}

// VerifySendMessage verifies that the given message is an external message ready to be sent to the blockchain.
func VerifySendMessage(msg *tlb.Message) error {
if msg.Info.SumType != "ExtInMsgInfo" {
return fmt.Errorf("external message must begin with ext_in_msg_info$10")
}
return nil
}

// ConvertSendMessagePayloadToMessage converts the given payload to a tlb.Message.
// It also verifies that the message is an external message ready to be sent to the blockchain.
func ConvertSendMessagePayloadToMessage(payload []byte) (*tlb.Message, error) {
Expand All @@ -31,8 +39,8 @@ func ConvertSendMessagePayloadToMessage(payload []byte) (*tlb.Message, error) {
if err := tlb.Unmarshal(root, &msg); err != nil {
return nil, fmt.Errorf("external message is not a tlb.Message")
}
if msg.Info.SumType != "ExtInMsgInfo" {
return nil, fmt.Errorf("external message must begin with ext_in_msg_info$10")
if err := VerifySendMessage(&msg); err != nil {
return nil, err
}
return &msg, nil
}
68 changes: 68 additions & 0 deletions message.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package tongo

import (
"encoding/base64"
"encoding/hex"
"fmt"

"github.com/tonkeeper/tongo/boc"
"github.com/tonkeeper/tongo/tlb"
"github.com/tonkeeper/tongo/ton"
)

func decodeBoc(bocStr string) ([]byte, error) {
bocData, err := base64.StdEncoding.DecodeString(bocStr)
if err != nil {
return hex.DecodeString(bocStr)
}
return bocData, nil
}

// Message contains a tlb.Message, its boc representation and a Cell.
type Message struct {
Boc []byte
TlbMsg *tlb.Message
Cell *boc.Cell
}

// ParseTlbMessage returns a Message unmarshalled from the given boc string.
// The boc string can be either in base64 or hex format.
func ParseTlbMessage(bocStr string) (*Message, error) {
b, err := decodeBoc(bocStr)
if err != nil {
return nil, err
}
cells, err := boc.DeserializeBoc(b)
if err != nil {
return nil, err
}
if len(cells) != 1 {
return nil, fmt.Errorf("invalid message boc")
}
var msg tlb.Message
if err := tlb.Unmarshal(cells[0], &msg); err != nil {
return nil, err
}
cells[0].ResetCounters()
return &Message{Boc: b, TlbMsg: &msg, Cell: cells[0]}, nil
}

func (m *Message) DestinationAccountID() (ton.AccountID, error) {
var dest tlb.MsgAddress
switch m.TlbMsg.Info.SumType {
case "IntMsgInfo":
dest = m.TlbMsg.Info.IntMsgInfo.Dest
case "ExtInMsgInfo":
dest = m.TlbMsg.Info.ExtInMsgInfo.Dest
case "ExtOutMsgInfo":
dest = m.TlbMsg.Info.ExtOutMsgInfo.Dest
}
accountID, err := ton.AccountIDFromTlb(dest)
if err != nil {
return ton.AccountID{}, err
}
if accountID == nil {
return ton.AccountID{}, fmt.Errorf("failed to extract the destination address")
}
return ton.AccountID{}, nil
}
33 changes: 22 additions & 11 deletions wallet/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ type RawMessage struct {
Mode byte
}

// ToTlbMessage converts a RawMessage to a tlb.Message.
func (rm *RawMessage) ToTlbMessage() (*tlb.Message, error) {
var msg tlb.Message
if err := tlb.Unmarshal(rm.Message, &msg); err != nil {
return nil, err
}
return &msg, nil
}

type PayloadV1toV4 []RawMessage
type PayloadHighload []RawMessage

Expand All @@ -59,20 +68,16 @@ func (body *SignedMsgBody) Verify(publicKey ed25519.PublicKey) error {
return fmt.Errorf("failed to verify msg signature")
}

func extractSignedMsgBody(msg *boc.Cell) (*SignedMsgBody, error) {
var m tlb.Message
if err := tlb.Unmarshal(msg, &m); err != nil {
return nil, err
}
func extractSignedMsgBody(msg *tlb.Message) (*SignedMsgBody, error) {
bodyCell := boc.Cell(msg.Body.Value)
msgBody := SignedMsgBody{}
bodyCell := boc.Cell(m.Body.Value)
if err := tlb.Unmarshal(&bodyCell, &msgBody); err != nil {
return nil, err
}
return &msgBody, nil
}

func DecodeMessageV4(msg *boc.Cell) (*MessageV4, error) {
func DecodeMessageV4(msg *tlb.Message) (*MessageV4, error) {
signedMsgBody, err := extractSignedMsgBody(msg)
if err != nil {
return nil, err
Expand All @@ -89,7 +94,7 @@ func decodeMessageV4(body *SignedMsgBody) (*MessageV4, error) {
return &msgv4, nil
}

func DecodeMessageV3(msg *boc.Cell) (*MessageV3, error) {
func DecodeMessageV3(msg *tlb.Message) (*MessageV3, error) {
signedMsgBody, err := extractSignedMsgBody(msg)
if err != nil {
return nil, err
Expand All @@ -106,7 +111,7 @@ func decodeMessageV3(body *SignedMsgBody) (*MessageV3, error) {
return &msgv3, nil
}

func DecodeHighloadV2Message(msg *boc.Cell) (*HighloadV2Message, error) {
func DecodeHighloadV2Message(msg *tlb.Message) (*HighloadV2Message, error) {
signedMsgBody, err := extractSignedMsgBody(msg)
if err != nil {
return nil, err
Expand All @@ -124,7 +129,10 @@ func decodeHighloadV2Message(body *SignedMsgBody) (*HighloadV2Message, error) {
}

// ExtractRawMessages extracts a list of RawMessages from an external message.
func ExtractRawMessages(ver Version, msg *boc.Cell) (PayloadV1toV4, error) {
func ExtractRawMessages(ver Version, msg *tlb.Message) (PayloadV1toV4, error) {
if msg == nil {
return nil, fmt.Errorf("msg is nil")
}
switch ver {
case V4R1, V4R2:
v4, err := DecodeMessageV4(msg)
Expand Down Expand Up @@ -154,7 +162,10 @@ func ExtractRawMessages(ver Version, msg *boc.Cell) (PayloadV1toV4, error) {
// was signed by the given public key of a wallet contract.
// On success, it returns nil.
// Otherwise, it returns an error.
func VerifySignature(ver Version, msg *boc.Cell, publicKey ed25519.PublicKey) error {
func VerifySignature(ver Version, msg *tlb.Message, publicKey ed25519.PublicKey) error {
if msg == nil {
return fmt.Errorf("msg is nil")
}
switch ver {
case V3R1, V3R2, V4R1, V4R2, HighLoadV2R2:
signedMsgBody, err := extractSignedMsgBody(msg)
Expand Down
6 changes: 5 additions & 1 deletion wallet/messages_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,11 @@ func TestExtractRawMessages(t *testing.T) {
if err != nil {
t.Fatal(err)
}
rawMessages, err := ExtractRawMessages(tt.ver, c[0])
var msg tlb.Message
if err := tlb.Unmarshal(c[0], &msg); err != nil {
t.Fatal(err)
}
rawMessages, err := ExtractRawMessages(tt.ver, &msg)
if err != nil {
t.Fatal(err)
}
Expand Down
5 changes: 4 additions & 1 deletion wallet/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,11 @@ func init() {
// GetWalletVersion returns a wallet version by the given state of an account and an incoming message to the account.
// An incoming message is needed in case when a wallet has not been initialized yet.
// In this case, we take its code from the message's StateInit.
func GetWalletVersion(state tlb.ShardAccount, msg tlb.Message) (Version, bool, error) {
func GetWalletVersion(state tlb.ShardAccount, msg *tlb.Message) (Version, bool, error) {
if state.Account.SumType == "AccountNone" || state.Account.Account.Storage.State.SumType == "AccountUninit" {
if msg == nil {
return 0, false, fmt.Errorf("account is not initialized")
}
if !msg.Init.Exists {
return 0, false, fmt.Errorf("account is not initialized")
}
Expand Down

0 comments on commit 9c6ebb4

Please sign in to comment.