Skip to content

Commit 831d00c

Browse files
committed
Merge remote-tracking branch 'origin/master'
2 parents 65b12cc + 2e03145 commit 831d00c

File tree

9 files changed

+289
-32
lines changed

9 files changed

+289
-32
lines changed

.github/workflows/test.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
- name: Go Version
1818
uses: actions/setup-go@v3
1919
with:
20-
go-version: '1.19'
20+
go-version: '1.21'
2121
- name: test
2222
env:
2323
LD_LIBRARY_PATH: ${{ github.workspace }}/libs

abi/generated_test.go

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,27 @@ func TestMessageDecoder(t *testing.T) {
461461
interfaces []ContractInterface
462462
wantValidate func(t *testing.T, value any)
463463
}{
464+
{
465+
name: "gram miner - submit proof of work",
466+
interfaces: []ContractInterface{GramMiner},
467+
wantOpName: "GramSubmitProofOfWork",
468+
boc: "te6ccgEBAQEAewAA8k1pbmUAZh5n6Ko92S+6JcXv0vZh3JgmUoAzO2R8CeNp7hvCAYZUe9AHyiw3HOIN5fq3UWUTxJ2NzkQQ8n/18ag79sePGkYAAACknATyivxe2NapVEVFPsjSyiw3HOIN5fq3UWUTxJ2NzkQQ8n/18ag79sePGkYAAAA=",
469+
wantValidate: func(t *testing.T, value any) {
470+
seed := big.Int{}
471+
seed.SetString("218803489964525407889229111495606847698", 10)
472+
body := GramSubmitProofOfWorkMsgBody{
473+
Flags: 0,
474+
Expire: 1713268712,
475+
Whom: mustToBits256("aa3dd92fba25c5efd2f661dc98265280333b647c09e369ee1bc20186547bd007"),
476+
Rdata1: mustToBits256("ca2c371ce20de5fab7516513c49d8dce4410f27ff5f1a83bf6c78f1a46000000"),
477+
Rseed: tlb.Uint128(seed),
478+
Rdata2: mustToBits256("ca2c371ce20de5fab7516513c49d8dce4410f27ff5f1a83bf6c78f1a46000000"),
479+
}
480+
if !reflect.DeepEqual(value, body) {
481+
t.Fatalf("got: %v, want: %v", value, body)
482+
}
483+
},
484+
},
464485
{
465486
name: "jetton burn notification",
466487
boc: "te6ccgEBAQEASAAAi3vdl952mKNkA9fVjzGM4ygA2ZpktQsYby0n9cV5VWOFINBjScIU2HdondFsK3lDpEB64AEuSPMwX2JvQ+QTUtfXxYKTyMA=",
@@ -1075,25 +1096,6 @@ func TestDecodeExternalIn(t *testing.T) {
10751096
wantOpName string
10761097
wantValue func() any
10771098
}{
1078-
{
1079-
name: "gram miner - submit proof of work",
1080-
interfaces: []ContractInterface{GramMiner},
1081-
wantOpName: "GramSubmitProofOfWork",
1082-
boc: "te6ccgEBAQEAewAA8k1pbmUAZh5n6Ko92S+6JcXv0vZh3JgmUoAzO2R8CeNp7hvCAYZUe9AHyiw3HOIN5fq3UWUTxJ2NzkQQ8n/18ag79sePGkYAAACknATyivxe2NapVEVFPsjSyiw3HOIN5fq3UWUTxJ2NzkQQ8n/18ag79sePGkYAAAA=",
1083-
wantValue: func() any {
1084-
seed := big.Int{}
1085-
seed.SetString("218803489964525407889229111495606847698", 10)
1086-
body := GramSubmitProofOfWorkMsgBody{
1087-
Flags: 0,
1088-
Expire: 1713268712,
1089-
Whom: mustToBits256("aa3dd92fba25c5efd2f661dc98265280333b647c09e369ee1bc20186547bd007"),
1090-
Rdata1: mustToBits256("ca2c371ce20de5fab7516513c49d8dce4410f27ff5f1a83bf6c78f1a46000000"),
1091-
Rseed: tlb.Uint128(seed),
1092-
Rdata2: mustToBits256("ca2c371ce20de5fab7516513c49d8dce4410f27ff5f1a83bf6c78f1a46000000"),
1093-
}
1094-
return body
1095-
},
1096-
},
10971099
{
10981100
name: "highload wallet v3 - jetton transfer",
10991101
interfaces: []ContractInterface{WalletHighloadV3R1},

abi/schemas/gram.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@
1515
</output>
1616
</get_method>
1717
<internal name="gram_submit_proof_of_work">
18-
payload#4d696e65 flags:uint8 expire:uint32 whom:bits256 rdata1:bits256 rseed:uint128 rdata2:bits256 = ExternalMsgBody;
18+
payload#4d696e65 flags:uint8 expire:uint32 whom:bits256 rdata1:bits256 rseed:uint128 rdata2:bits256 = InternalMsgBody;
1919
</internal>
2020
</abi>

liteclient/client_test.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"fmt"
88
"os"
99
"testing"
10-
"time"
1110

1211
"github.com/tonkeeper/tongo/config"
1312
)
@@ -54,14 +53,11 @@ func TestGeneratedMethod(t *testing.T) {
5453
}
5554

5655
client := NewClient(c)
57-
for {
58-
resp, err := client.LiteServerGetMasterchainInfo(context.Background())
59-
if err != nil {
60-
panic(err)
61-
}
62-
fmt.Printf("Last seqno: %d\n", resp.Last.Seqno)
63-
time.Sleep(1 * time.Second)
56+
resp, err := client.LiteServerGetMasterchainInfo(context.Background())
57+
if err != nil {
58+
panic(err)
6459
}
60+
fmt.Printf("Last seqno: %d\n", resp.Last.Seqno)
6561
}
6662

6763
func TestGeneratedMethod2(t *testing.T) {

tlb/generator.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"github.com/tonkeeper/tongo/tlb/parser"
1010
)
1111

12-
var bitsSizes = []int{96, 256, 264, 320, 352, 512}
12+
var bitsSizes = []int{80, 96, 256, 264, 320, 352, 512}
1313
var intSizes = []int{128, 256, 257}
1414

1515
func main() {

tlb/integers.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6100,6 +6100,36 @@ func (u *Int257) UnmarshalJSON(p []byte) error {
61006100
return nil
61016101
}
61026102

6103+
type Bits80 [10]byte
6104+
6105+
func (u Bits80) FixedSize() int {
6106+
return 80
6107+
}
6108+
6109+
func (u Bits80) MarshalJSON() ([]byte, error) {
6110+
return []byte(fmt.Sprintf("\"%x\"", u[:])), nil
6111+
}
6112+
6113+
func (u *Bits80) UnmarshalJSON(b []byte) error {
6114+
bs, err := hex.DecodeString(strings.Trim(string(b), "\""))
6115+
if err != nil {
6116+
return err
6117+
}
6118+
if len(bs) != 10 {
6119+
return fmt.Errorf("can't parse Bits80 %v", string(b))
6120+
}
6121+
copy(u[:], bs)
6122+
return nil
6123+
}
6124+
6125+
func (u Bits80) Equal(other any) bool {
6126+
otherBits, ok := other.(Bits80)
6127+
if !ok {
6128+
return false
6129+
}
6130+
return u == otherBits
6131+
}
6132+
61036133
type Bits96 [12]byte
61046134

61056135
func (u Bits96) FixedSize() int {

wallet/messages.go

Lines changed: 141 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ package wallet
22

33
import (
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+
1114
type 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+
2763
type 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

6298
func 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+
75124
func 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.
127176
func 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

Comments
 (0)