Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
mr-tron committed May 1, 2024
2 parents 65b12cc + 2e03145 commit 831d00c
Show file tree
Hide file tree
Showing 9 changed files with 289 additions and 32 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Go Version
uses: actions/setup-go@v3
with:
go-version: '1.19'
go-version: '1.21'
- name: test
env:
LD_LIBRARY_PATH: ${{ github.workspace }}/libs
Expand Down
40 changes: 21 additions & 19 deletions abi/generated_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,27 @@ func TestMessageDecoder(t *testing.T) {
interfaces []ContractInterface
wantValidate func(t *testing.T, value any)
}{
{
name: "gram miner - submit proof of work",
interfaces: []ContractInterface{GramMiner},
wantOpName: "GramSubmitProofOfWork",
boc: "te6ccgEBAQEAewAA8k1pbmUAZh5n6Ko92S+6JcXv0vZh3JgmUoAzO2R8CeNp7hvCAYZUe9AHyiw3HOIN5fq3UWUTxJ2NzkQQ8n/18ag79sePGkYAAACknATyivxe2NapVEVFPsjSyiw3HOIN5fq3UWUTxJ2NzkQQ8n/18ag79sePGkYAAAA=",
wantValidate: func(t *testing.T, value any) {
seed := big.Int{}
seed.SetString("218803489964525407889229111495606847698", 10)
body := GramSubmitProofOfWorkMsgBody{
Flags: 0,
Expire: 1713268712,
Whom: mustToBits256("aa3dd92fba25c5efd2f661dc98265280333b647c09e369ee1bc20186547bd007"),
Rdata1: mustToBits256("ca2c371ce20de5fab7516513c49d8dce4410f27ff5f1a83bf6c78f1a46000000"),
Rseed: tlb.Uint128(seed),
Rdata2: mustToBits256("ca2c371ce20de5fab7516513c49d8dce4410f27ff5f1a83bf6c78f1a46000000"),
}
if !reflect.DeepEqual(value, body) {
t.Fatalf("got: %v, want: %v", value, body)
}
},
},
{
name: "jetton burn notification",
boc: "te6ccgEBAQEASAAAi3vdl952mKNkA9fVjzGM4ygA2ZpktQsYby0n9cV5VWOFINBjScIU2HdondFsK3lDpEB64AEuSPMwX2JvQ+QTUtfXxYKTyMA=",
Expand Down Expand Up @@ -1075,25 +1096,6 @@ func TestDecodeExternalIn(t *testing.T) {
wantOpName string
wantValue func() any
}{
{
name: "gram miner - submit proof of work",
interfaces: []ContractInterface{GramMiner},
wantOpName: "GramSubmitProofOfWork",
boc: "te6ccgEBAQEAewAA8k1pbmUAZh5n6Ko92S+6JcXv0vZh3JgmUoAzO2R8CeNp7hvCAYZUe9AHyiw3HOIN5fq3UWUTxJ2NzkQQ8n/18ag79sePGkYAAACknATyivxe2NapVEVFPsjSyiw3HOIN5fq3UWUTxJ2NzkQQ8n/18ag79sePGkYAAAA=",
wantValue: func() any {
seed := big.Int{}
seed.SetString("218803489964525407889229111495606847698", 10)
body := GramSubmitProofOfWorkMsgBody{
Flags: 0,
Expire: 1713268712,
Whom: mustToBits256("aa3dd92fba25c5efd2f661dc98265280333b647c09e369ee1bc20186547bd007"),
Rdata1: mustToBits256("ca2c371ce20de5fab7516513c49d8dce4410f27ff5f1a83bf6c78f1a46000000"),
Rseed: tlb.Uint128(seed),
Rdata2: mustToBits256("ca2c371ce20de5fab7516513c49d8dce4410f27ff5f1a83bf6c78f1a46000000"),
}
return body
},
},
{
name: "highload wallet v3 - jetton transfer",
interfaces: []ContractInterface{WalletHighloadV3R1},
Expand Down
2 changes: 1 addition & 1 deletion abi/schemas/gram.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@
</output>
</get_method>
<internal name="gram_submit_proof_of_work">
payload#4d696e65 flags:uint8 expire:uint32 whom:bits256 rdata1:bits256 rseed:uint128 rdata2:bits256 = ExternalMsgBody;
payload#4d696e65 flags:uint8 expire:uint32 whom:bits256 rdata1:bits256 rseed:uint128 rdata2:bits256 = InternalMsgBody;
</internal>
</abi>
12 changes: 4 additions & 8 deletions liteclient/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"fmt"
"os"
"testing"
"time"

"github.com/tonkeeper/tongo/config"
)
Expand Down Expand Up @@ -54,14 +53,11 @@ func TestGeneratedMethod(t *testing.T) {
}

client := NewClient(c)
for {
resp, err := client.LiteServerGetMasterchainInfo(context.Background())
if err != nil {
panic(err)
}
fmt.Printf("Last seqno: %d\n", resp.Last.Seqno)
time.Sleep(1 * time.Second)
resp, err := client.LiteServerGetMasterchainInfo(context.Background())
if err != nil {
panic(err)
}
fmt.Printf("Last seqno: %d\n", resp.Last.Seqno)
}

func TestGeneratedMethod2(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion tlb/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"github.com/tonkeeper/tongo/tlb/parser"
)

var bitsSizes = []int{96, 256, 264, 320, 352, 512}
var bitsSizes = []int{80, 96, 256, 264, 320, 352, 512}
var intSizes = []int{128, 256, 257}

func main() {
Expand Down
30 changes: 30 additions & 0 deletions tlb/integers.go
Original file line number Diff line number Diff line change
Expand Up @@ -6100,6 +6100,36 @@ func (u *Int257) UnmarshalJSON(p []byte) error {
return nil
}

type Bits80 [10]byte

func (u Bits80) FixedSize() int {
return 80
}

func (u Bits80) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf("\"%x\"", u[:])), nil
}

func (u *Bits80) UnmarshalJSON(b []byte) error {
bs, err := hex.DecodeString(strings.Trim(string(b), "\""))
if err != nil {
return err
}
if len(bs) != 10 {
return fmt.Errorf("can't parse Bits80 %v", string(b))
}
copy(u[:], bs)
return nil
}

func (u Bits80) Equal(other any) bool {
otherBits, ok := other.(Bits80)
if !ok {
return false
}
return u == otherBits
}

type Bits96 [12]byte

func (u Bits96) FixedSize() int {
Expand Down
142 changes: 141 additions & 1 deletion wallet/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ package wallet

import (
"crypto/ed25519"
"errors"
"fmt"

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

var ErrBadSignature = errors.New("failed to verify msg signature")

type MessageV3 struct {
SubWalletId uint32
ValidUntil uint32
Expand All @@ -24,6 +27,39 @@ type MessageV4 struct {
RawMessages PayloadV1toV4
}

type SendMessageAction struct {
Magic tlb.Magic `tlb:"#0ec3c86d"`
Mode uint8
Msg *boc.Cell `tlb:"^"`
}

type SendMessageList struct {
Actions []SendMessageAction
}

// MessageV5 is a message format used by wallet v5.
type MessageV5 struct {
tlb.SumType
// Sint is an internal message authenticated by a signature.
Sint struct {
SubWalletId tlb.Bits80
ValidUntil uint32
Seqno uint32
Op bool
Signature tlb.Bits512
Actions SendMessageList `tlb:"^"`
} `tlbSumType:"#73696e74"`
// Sign is an external message authenticated by a signature.
Sign struct {
SubWalletId tlb.Bits80
ValidUntil uint32
Seqno uint32
Op bool
Signature tlb.Bits512
Actions SendMessageList `tlb:"^"`
} `tlbSumType:"#7369676e"`
}

type HighloadV2Message struct {
SubWalletId uint32
BoundedQueryID uint64
Expand Down Expand Up @@ -56,7 +92,7 @@ func (body *SignedMsgBody) Verify(publicKey ed25519.PublicKey) error {
if ed25519.Verify(publicKey, hash, body.Sign[:]) {
return nil
}
return fmt.Errorf("failed to verify msg signature")
return ErrBadSignature
}

func extractSignedMsgBody(msg *boc.Cell) (*SignedMsgBody, error) {
Expand All @@ -72,6 +108,19 @@ func extractSignedMsgBody(msg *boc.Cell) (*SignedMsgBody, error) {
return &msgBody, nil
}

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

func DecodeMessageV4(msg *boc.Cell) (*MessageV4, error) {
signedMsgBody, err := extractSignedMsgBody(msg)
if err != nil {
Expand Down Expand Up @@ -126,6 +175,12 @@ func decodeHighloadV2Message(body *SignedMsgBody) (*HighloadV2Message, error) {
// ExtractRawMessages extracts a list of RawMessages from an external message.
func ExtractRawMessages(ver Version, msg *boc.Cell) ([]RawMessage, error) {
switch ver {
case V5R1:
v5, err := DecodeMessageV5(msg)
if err != nil {
return nil, err
}
return v5.RawMessages(), nil
case V4R1, V4R2:
v4, err := DecodeMessageV4(msg)
if err != nil {
Expand Down Expand Up @@ -259,3 +314,88 @@ func (p *PayloadHighload) UnmarshalTLB(c *boc.Cell, decoder *tlb.Decoder) error
*p = rawMessages
return nil
}

func (l *SendMessageList) UnmarshalTLB(c *boc.Cell, decoder *tlb.Decoder) error {
var actions []SendMessageAction
for {
switch c.BitsAvailableForRead() {
case 0:
l.Actions = actions
return nil
case 40:
next, err := c.NextRef()
if err != nil {
return err
}
var action SendMessageAction
if err := decoder.Unmarshal(c, &action); err != nil {
return err
}
actions = append(actions, action)
c = next
default:
return fmt.Errorf("unexpected bits available: %v", c.BitsAvailableForRead())
}
}
}

func MessageV5VerifySignature(msgBody boc.Cell, publicKey ed25519.PublicKey) error {
totalBits := msgBody.BitsAvailableForRead()
if totalBits < 512 {
return fmt.Errorf("not enough bits in the cell")
}
bits, err := msgBody.ReadBits(totalBits - 512)
if err != nil {
return err
}
signature, err := msgBody.ReadBytes(64)
if err != nil {
return err
}
msgCopy := boc.NewCell()
if err := msgCopy.WriteBitString(bits); err != nil {
return err
}
for i := 0; i < msgBody.RefsSize(); i++ {
ref, err := msgBody.NextRef()
if err != nil {
return err
}
if err := msgCopy.AddRef(ref); err != nil {
return err
}
}
hash, err := msgCopy.Hash()
if err != nil {
return err
}
if ed25519.Verify(publicKey, hash, signature) {
return nil
}
return ErrBadSignature
}

func (m *MessageV5) RawMessages() []RawMessage {
switch m.SumType {
case "Sint":
msgs := make([]RawMessage, 0, len(m.Sint.Actions.Actions))
for _, action := range m.Sint.Actions.Actions {
msgs = append(msgs, RawMessage{
Message: action.Msg,
Mode: action.Mode,
})
}
return msgs
case "Sign":
msgs := make([]RawMessage, 0, len(m.Sign.Actions.Actions))
for _, action := range m.Sign.Actions.Actions {
msgs = append(msgs, RawMessage{
Message: action.Msg,
Mode: action.Mode,
})
}
return msgs
default:
return nil
}
}
Loading

0 comments on commit 831d00c

Please sign in to comment.