go-substrate-rpc-client
go-substrate-rpc-client copied to clipboard
SubmitExtrinsic Verification Error
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
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 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
}

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
@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
How can I resolve this error?
Thanks
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
)
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?