@@ -2,12 +2,15 @@ package wallet
22
33import (
44 "crypto/ed25519"
5+ "errors"
56 "fmt"
67
78 "github.com/tonkeeper/tongo/boc"
89 "github.com/tonkeeper/tongo/tlb"
910)
1011
12+ var ErrBadSignature = errors .New ("failed to verify msg signature" )
13+
1114type MessageV3 struct {
1215 SubWalletId uint32
1316 ValidUntil uint32
@@ -24,6 +27,39 @@ type MessageV4 struct {
2427 RawMessages PayloadV1toV4
2528}
2629
30+ type SendMessageAction struct {
31+ Magic tlb.Magic `tlb:"#0ec3c86d"`
32+ Mode uint8
33+ Msg * boc.Cell `tlb:"^"`
34+ }
35+
36+ type SendMessageList struct {
37+ Actions []SendMessageAction
38+ }
39+
40+ // MessageV5 is a message format used by wallet v5.
41+ type MessageV5 struct {
42+ tlb.SumType
43+ // Sint is an internal message authenticated by a signature.
44+ Sint struct {
45+ SubWalletId tlb.Bits80
46+ ValidUntil uint32
47+ Seqno uint32
48+ Op bool
49+ Signature tlb.Bits512
50+ Actions SendMessageList `tlb:"^"`
51+ } `tlbSumType:"#73696e74"`
52+ // Sign is an external message authenticated by a signature.
53+ Sign struct {
54+ SubWalletId tlb.Bits80
55+ ValidUntil uint32
56+ Seqno uint32
57+ Op bool
58+ Signature tlb.Bits512
59+ Actions SendMessageList `tlb:"^"`
60+ } `tlbSumType:"#7369676e"`
61+ }
62+
2763type HighloadV2Message struct {
2864 SubWalletId uint32
2965 BoundedQueryID uint64
@@ -56,7 +92,7 @@ func (body *SignedMsgBody) Verify(publicKey ed25519.PublicKey) error {
5692 if ed25519 .Verify (publicKey , hash , body .Sign [:]) {
5793 return nil
5894 }
59- return fmt . Errorf ( "failed to verify msg signature" )
95+ return ErrBadSignature
6096}
6197
6298func extractSignedMsgBody (msg * boc.Cell ) (* SignedMsgBody , error ) {
@@ -72,6 +108,19 @@ func extractSignedMsgBody(msg *boc.Cell) (*SignedMsgBody, error) {
72108 return & msgBody , nil
73109}
74110
111+ func DecodeMessageV5 (msg * boc.Cell ) (* MessageV5 , error ) {
112+ var m tlb.Message
113+ if err := tlb .Unmarshal (msg , & m ); err != nil {
114+ return nil , err
115+ }
116+ var msgv5 MessageV5
117+ bodyCell := boc .Cell (m .Body .Value )
118+ if err := tlb .Unmarshal (& bodyCell , & msgv5 ); err != nil {
119+ return nil , err
120+ }
121+ return & msgv5 , nil
122+ }
123+
75124func DecodeMessageV4 (msg * boc.Cell ) (* MessageV4 , error ) {
76125 signedMsgBody , err := extractSignedMsgBody (msg )
77126 if err != nil {
@@ -126,6 +175,12 @@ func decodeHighloadV2Message(body *SignedMsgBody) (*HighloadV2Message, error) {
126175// ExtractRawMessages extracts a list of RawMessages from an external message.
127176func ExtractRawMessages (ver Version , msg * boc.Cell ) ([]RawMessage , error ) {
128177 switch ver {
178+ case V5R1 :
179+ v5 , err := DecodeMessageV5 (msg )
180+ if err != nil {
181+ return nil , err
182+ }
183+ return v5 .RawMessages (), nil
129184 case V4R1 , V4R2 :
130185 v4 , err := DecodeMessageV4 (msg )
131186 if err != nil {
@@ -259,3 +314,88 @@ func (p *PayloadHighload) UnmarshalTLB(c *boc.Cell, decoder *tlb.Decoder) error
259314 * p = rawMessages
260315 return nil
261316}
317+
318+ func (l * SendMessageList ) UnmarshalTLB (c * boc.Cell , decoder * tlb.Decoder ) error {
319+ var actions []SendMessageAction
320+ for {
321+ switch c .BitsAvailableForRead () {
322+ case 0 :
323+ l .Actions = actions
324+ return nil
325+ case 40 :
326+ next , err := c .NextRef ()
327+ if err != nil {
328+ return err
329+ }
330+ var action SendMessageAction
331+ if err := decoder .Unmarshal (c , & action ); err != nil {
332+ return err
333+ }
334+ actions = append (actions , action )
335+ c = next
336+ default :
337+ return fmt .Errorf ("unexpected bits available: %v" , c .BitsAvailableForRead ())
338+ }
339+ }
340+ }
341+
342+ func MessageV5VerifySignature (msgBody boc.Cell , publicKey ed25519.PublicKey ) error {
343+ totalBits := msgBody .BitsAvailableForRead ()
344+ if totalBits < 512 {
345+ return fmt .Errorf ("not enough bits in the cell" )
346+ }
347+ bits , err := msgBody .ReadBits (totalBits - 512 )
348+ if err != nil {
349+ return err
350+ }
351+ signature , err := msgBody .ReadBytes (64 )
352+ if err != nil {
353+ return err
354+ }
355+ msgCopy := boc .NewCell ()
356+ if err := msgCopy .WriteBitString (bits ); err != nil {
357+ return err
358+ }
359+ for i := 0 ; i < msgBody .RefsSize (); i ++ {
360+ ref , err := msgBody .NextRef ()
361+ if err != nil {
362+ return err
363+ }
364+ if err := msgCopy .AddRef (ref ); err != nil {
365+ return err
366+ }
367+ }
368+ hash , err := msgCopy .Hash ()
369+ if err != nil {
370+ return err
371+ }
372+ if ed25519 .Verify (publicKey , hash , signature ) {
373+ return nil
374+ }
375+ return ErrBadSignature
376+ }
377+
378+ func (m * MessageV5 ) RawMessages () []RawMessage {
379+ switch m .SumType {
380+ case "Sint" :
381+ msgs := make ([]RawMessage , 0 , len (m .Sint .Actions .Actions ))
382+ for _ , action := range m .Sint .Actions .Actions {
383+ msgs = append (msgs , RawMessage {
384+ Message : action .Msg ,
385+ Mode : action .Mode ,
386+ })
387+ }
388+ return msgs
389+ case "Sign" :
390+ msgs := make ([]RawMessage , 0 , len (m .Sign .Actions .Actions ))
391+ for _ , action := range m .Sign .Actions .Actions {
392+ msgs = append (msgs , RawMessage {
393+ Message : action .Msg ,
394+ Mode : action .Mode ,
395+ })
396+ }
397+ return msgs
398+ default :
399+ return nil
400+ }
401+ }
0 commit comments