go-substrate-rpc-client icon indicating copy to clipboard operation
go-substrate-rpc-client copied to clipboard

SubmitExtrinsic Verification Error

Open jekabolt opened this issue 2 years ago • 6 comments

Im using chain DataHighway Tanganika Kusama Parachain using DataHighway Collator v3.6.0-b938f49-x86_64-linux-gnu

trying to SubmitExtrinsic

my code below

func TestTransfer(t *testing.T) {
	// This sample shows how to create a transaction to make a transfer from one an account to another.

	// Instantiate the API
	api, err := gsrpc.NewSubstrateAPI("wss://tanganika.datahighway.com")
	if err != nil {
		panic(err)
	}

	meta, err := api.RPC.State.GetMetadataLatest()
	if err != nil {
		panic(err)
	}

	kpFrom, err := signature.KeyringPairFromSecret("secret1", 33)
	assert.NoError(t, err)

	kpTo, err := signature.KeyringPairFromSecret("secret2", 33)
	assert.NoError(t, err)

	addrTo, err := types.NewMultiAddressFromHexAccountID(types.HexEncodeToString(kpTo.PublicKey))

	// 1 unit of transfer
	bal, ok := new(big.Int).SetString("10000000000000", 10)
	if !ok {
		panic(fmt.Errorf("failed to convert balance"))
	}

	c, err := types.NewCall(meta, "Balances.transfer", addrTo, types.NewUCompact(bal))
	if err != nil {
		panic(err)
	}

	// Create the extrinsic
	ext := types.NewExtrinsic(c)

	genesisHash, err := api.RPC.Chain.GetBlockHash(0)
	if err != nil {
		panic(err)
	}

	rv, err := api.RPC.State.GetRuntimeVersionLatest()
	if err != nil {
		panic(err)
	}

	key, err := types.CreateStorageKey(meta, "System", "Account", kpFrom.PublicKey)
	if err != nil {
		panic(err)
	}

	var accountInfo types.AccountInfo
	ok, err = api.RPC.State.GetStorageLatest(key, &accountInfo)
	if err != nil || !ok {
		panic(err)
	}

	nonce := uint32(accountInfo.Nonce)
	o := types.SignatureOptions{
		BlockHash:          genesisHash,
		Era:                types.ExtrinsicEra{IsMortalEra: false},
		GenesisHash:        genesisHash,
		Nonce:              types.NewUCompactFromUInt(uint64(nonce)),
		SpecVersion:        rv.SpecVersion,
		Tip:                types.NewUCompactFromUInt(100),
		TransactionVersion: rv.TransactionVersion,
	}

	// Sign the transaction using Alice's default account
	err = ext.Sign(kpFrom, o)
	if err != nil {
		panic(err)
	}

	enc, err := types.EncodeToHex(ext)
	if err != nil {
		panic(err)
	}
	fmt.Println("tx --- ", enc)
	// Send the extrinsic
	_, err = api.RPC.Author.SubmitExtrinsic(ext)
	if err != nil {
		t.Errorf("SubmitExtrinsic %v", err)
	}

}

Im getting

SubmitExtrinsic Verification Error: Runtime error: Execution failed: Execution aborted due to trap: wasm trap: wasm `unreachable` instruction executed
        WASM backtrace:

            0: 0x324fa5 - <unknown>!rust_begin_unwind
            1: 0x35bc - <unknown>!core::panicking::panic_fmt::h8f11323637b4db3b
            2: 0x21812f - <unknown>!TaggedTransactionQueue_validate_transaction

any ideas what is wrong

jekabolt avatar Aug 03 '22 14:08 jekabolt

We solved this by decode the correct tx signed message from PolkadotJS. And we found out the go-rpc code writes the TX message in a wrong sequence

0x390284005675bfca5d558c0df741ce6017beb274d97f262144441f8d622f7e62bb0e411c0168d01fbd9c7849bfdb51cde9d7a3494e1e7af22160f2a361f3672168f5d9085db91a24ea9d9a9d3c9bdaa8f7a347c28a0e4f930aa7e8f0af484547086b9aca89002400000f00009425ad96a3583bfe7de1f0a722ee7bbe9ddcaf3b4b79468ca74fe1b6b99c540c0284d717

https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Ftanganika.datahighway.com#/extrinsics/decode

After sorting it right, we can submit this extrinsic correctly.

sheenhx avatar Aug 09 '22 13:08 sheenhx

@sheenhx Hey I didn't get what do you mean I found that SectionIndex & MethodIndex are in wrong places and for browser generated tx they push SectionIndex in front of args

func NewCall(m *types.Metadata, call string, args ...interface{}) (types.Call, error) {
	c, err := m.FindCallIndex(call)
	if err != nil {
		return types.Call{}, err
	}
	c = types.CallIndex{
		SectionIndex: c.MethodIndex,
		MethodIndex:  c.SectionIndex,
	}

	var a []byte
	ci, err := types.Encode(c.SectionIndex)
	if err != nil {
		return types.Call{}, err
	}
	a = append(a, ci...)

	for _, arg := range args {
		e, err := types.Encode(arg)
		if err != nil {
			return types.Call{}, err
		}
		a = append(a, e...)
	}

	return types.Call{
		CallIndex: c,
		Args:      a,
	}, nil
}
image

here I got two nearly identical txs

0x4d028400d624d7a4c7ad34cdd007428709b610d529649e273567c4d7ea37854cec44152601f0a0af61cfc657295bc22cb93e07272b00679edbc21d3cfeb9d188782d5fcd6a9f448bb998109b98a3461e037a915f6596e71b2f646bcb48bc14ba6cb0d49389002800000f00005675bfca5d558c0df741ce6017beb274d97f262144441f8d622f7e62bb0e411c13000064a7b3b6e00d ```
this one from browser 

0x4d028400d624d7a4c7ad34cdd007428709b610d529649e273567c4d7ea37854cec441526011232c17b4a23edfeb8cda558721c8892af458ceccf0e17a618d31f6c7a66d43d64ddcaed7fa1cbe0593fd340958c7129ac9ca10eac86ff8f8fff7715cd5cf884002800000f00005675bfca5d558c0df741ce6017beb274d97f262144441f8d622f7e62bb0e411c13000064a7b3b6e00d```

and one I generate from code only difference in them is sig field and if I try to submit em via browser it gives error :

1010: Invalid Transaction: Transaction has a bad signature

jekabolt avatar Aug 12 '22 11:08 jekabolt

@sheenhx I took payload from generated tx

payload 0x000f00005675bfca5d558c0df741ce6017beb274d97f262144441f8d622f7e62bb0e411c13000064a7b3b6e00d0028000400000001000000eacdd2d5b42de9769ccbb6e8d9013ab0d90ab105bf601d4aac53e874c145ec21eacdd2d5b42de9769ccbb6e8d9013ab0d90ab105bf601d4aac53e874c145

and signature

0x1232c17b4a23edfeb8cda558721c8892af458ceccf0e17a618d31f6c7a66d43d64ddcaed7fa1cbe0593fd340958c7129ac9ca10eac86ff8f8fff7715cd5cf884

they are totally fine and pass

ok, err := signature.Verify(b, sig[:], signature.TestKeyringPairAlice.URI)

and browser verification

jekabolt avatar Aug 12 '22 12:08 jekabolt

How can I resolve this error?

Thanks

jekabolt avatar Aug 12 '22 12:08 jekabolt

I have the same issue. Any solutions? I am using the latest version 4.1.0

My blockchain node version: polkadot-v0.9.36 This is my code example:

package main

import (
	"fmt"
	"github.com/centrifuge/go-substrate-rpc-client/v4/signature"
	"github.com/centrifuge/go-substrate-rpc-client/v4/types"
	gsrpc "github.com/centrifuge/go-substrate-rpc-client/v4"

)

func main(){
	err := SendData();

	if err != nil {
		fmt.Println("error:",err)
	
	}

}


func SendData() error {
        //Alice private key 
	nemo := "0xe5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a"

	api, err := gsrpc.NewSubstrateAPI("ws://127.0.0.1:9944")
	if err != nil {
		return err
	}
	fmt.Println("connected")

	keypair, err := signature.KeyringPairFromSecret(nemo, 42)
	fmt.Println("keypair", keypair.Address, keypair.PublicKey, keypair.URI)
	if err != nil {
		fmt.Println("keypair", err)
	}
	meta, err := api.RPC.State.GetMetadataLatest()
	if err != nil {
		return err
	}

	amount := types.NewUCompactFromUInt(2000000000000000000)

	bob, err := types.NewMultiAddressFromHexAccountID("0x8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48")
	c, err := types.NewCall(meta, "Balances.transfer",bob, amount)
	if err != nil {
		fmt.Println("err call", err)
		return err
	}
	fmt.Println("done1")
	// Create the extrinsic
	ext := types.NewExtrinsic(c)
	fmt.Println("ext:",ext.Version)


	genesisHash, err := api.RPC.Chain.GetBlockHash(0)
	if err != nil {
		fmt.Println("genesisHash, err", err)
		return err
	}
	fmt.Println("done 2 genesisHash", genesisHash)
	rv, err := api.RPC.State.GetRuntimeVersionLatest()
	if err != nil {
		fmt.Println("GetRuntimeVersionLatest, err", err)
		return err
	}
	fmt.Println("done 3")
	key, err := types.CreateStorageKey(meta, "System", "Account", keypair.PublicKey)
	if err != nil {
		return err
	}
	fmt.Println("done 4 key ", key)
	var accountInfo types.AccountInfo
	ok, err := api.RPC.State.GetStorageLatest(key, &accountInfo)
	fmt.Println("done 5", ok, err, accountInfo)
	if err != nil || !ok {
		return err
	}

	nonce := uint32(accountInfo.Nonce)
	o := types.SignatureOptions{
		BlockHash:          genesisHash,
		Era:                types.ExtrinsicEra{IsMortalEra: false},
		GenesisHash:        genesisHash,
		Nonce:              types.NewUCompactFromUInt(uint64(nonce)),
		SpecVersion:        rv.SpecVersion,
		Tip:                types.NewUCompactFromUInt(100),
		TransactionVersion: rv.TransactionVersion,
	}
	fmt.Println("before sign:",o)
	// Sign the transaction using Alice's default account
	err = ext.Sign(keypair, o)
	if err != nil {
		return err
	}
	fmt.Println("before submission")
	// Send the extrinsic
	txnHash, err := api.RPC.Author.SubmitAndWatchExtrinsic(ext)
	if err != nil {
		return err
	}
	fmt.Println("after submission txnHash", txnHash)
	return nil
}

My go.mod

module test-sign-transaction

go 1.18

require github.com/centrifuge/go-substrate-rpc-client/v4 v4.1.0

require (
	github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect
	github.com/cosmos/go-bip39 v1.0.0 // indirect
	github.com/deckarep/golang-set v1.8.0 // indirect
	github.com/decred/base58 v1.0.4 // indirect
	github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect
	github.com/ethereum/go-ethereum v1.10.20 // indirect
	github.com/go-stack/stack v1.8.1 // indirect
	github.com/gorilla/websocket v1.5.0 // indirect
	github.com/gtank/merlin v0.1.1 // indirect
	github.com/gtank/ristretto255 v0.1.2 // indirect
	github.com/mimoo/StrobeGo v0.0.0-20220103164710-9a04d6ca976b // indirect
	github.com/pierrec/xxHash v0.1.5 // indirect
	github.com/rs/cors v1.8.2 // indirect
	github.com/vedhavyas/go-subkey v1.0.4 // indirect
	golang.org/x/crypto v0.7.0 // indirect
	golang.org/x/sys v0.6.0 // indirect
	gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
)


CocDap avatar Sep 19 '23 06:09 CocDap

It could be that other chains use different kind of tips for signature options, or different signatures, one example can be found here - https://github.com/centrifuge/go-substrate-rpc-client/blob/master/registry/retriever/extrinsic_retriever_live_test.go#L24

The polkadot JS endpoint that you provided, https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Ftanganika.datahighway.com#/extrinsics/decode, does not seem to work. Is there another endpoint that we can use to check this particular issue?

cdamian avatar Dec 05 '23 12:12 cdamian