Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tongo.ParseTlbMessage() and change some funcs to accept tlb.Message #215

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 *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
Loading