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

SubmitExtrinsic Verification Error #284

Open
jekabolt opened this issue Aug 3, 2022 · 6 comments
Open

SubmitExtrinsic Verification Error #284

jekabolt opened this issue Aug 3, 2022 · 6 comments

Comments

@jekabolt
Copy link

jekabolt commented Aug 3, 2022

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

@sheenhx
Copy link

sheenhx commented Aug 9, 2022

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.

@jekabolt
Copy link
Author

@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
Copy link
Author

jekabolt commented Aug 12, 2022

@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
Copy link
Author

How can I resolve this error?

Thanks

@CocDap
Copy link

CocDap commented Sep 19, 2023

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
)

@cdamian
Copy link
Contributor

cdamian commented Dec 5, 2023

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants