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

Polkadot cannot sign DynamicExtrinsic #401

Open
YuXiaoCoder opened this issue Sep 12, 2024 · 2 comments
Open

Polkadot cannot sign DynamicExtrinsic #401

YuXiaoCoder opened this issue Sep 12, 2024 · 2 comments

Comments

@YuXiaoCoder
Copy link

Error message: panic: creating payload: signed extension 'PrevalidateAttests' is not supported

Here's the sample code

func Transfer(keyPair signature.KeyringPair) {
	// 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://polkadot-rpc.dwellir.com")
	if err != nil {
		panic(err)
	}

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

	bob, err := types.NewMultiAddressFromHexAccountID("0x1e635742bc09f1299c2934cbc46266a8c6b5756bc261fc0a970b6a51d1a4d053")
	if err != nil {
		panic(err)
	}

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

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

	ext := extrinsic.NewDynamicExtrinsic(&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", keyPair.PublicKey)
	if err != nil {
		panic(err)
	}

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

	err = ext.Sign(
		keyPair,
		meta,
		extrinsic.WithEra(types.ExtrinsicEra{IsImmortalEra: true}, genesisHash),
		extrinsic.WithNonce(types.NewUCompactFromUInt(uint64(accountInfo.Nonce))),
		extrinsic.WithTip(types.NewUCompactFromUInt(0)),
		extrinsic.WithSpecVersion(rv.SpecVersion),
		extrinsic.WithTransactionVersion(rv.TransactionVersion),
		extrinsic.WithGenesisHash(genesisHash),
		extrinsic.WithMetadataMode(extensions.CheckMetadataModeDisabled, extensions.CheckMetadataHash{Hash: types.NewEmptyOption[types.H256]()}),
		extrinsic.WithAssetID(types.NewEmptyOption[types.AssetID]()),
	)

	if err != nil {
		panic(err)
	}

	encodedExt, err := codec.EncodeToHex(ext)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Ext - %s\n", encodedExt)

	sub, err := api.RPC.Author.SubmitAndWatchDynamicExtrinsic(ext)
	if err != nil {
		panic(err)
	}
	defer sub.Unsubscribe()

	for {
		select {
		case st := <-sub.Chan():
			extStatus, _ := st.MarshalJSON()
			fmt.Printf("Status for transaction - %s\n", string(extStatus))
		case err := <-sub.Err():
			panic(err)
		}
	}
}
@YuXiaoCoder
Copy link
Author

YuXiaoCoder commented Sep 12, 2024

Using the previous approach is also not feasible

func Transfer(keyingPair signature.KeyringPair) {
	// Instantiate the API
	api, err := gsrpc.NewSubstrateAPI("wss://polkadot-rpc.dwellir.com")
	if err != nil {
		panic(err)
	}

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

	bob, err := types.NewMultiAddressFromHexAccountID("0x1e635742bc09f1299c2934cbc46266a8c6b5756bc261fc0a970b6a51d1a4d053")
	if err != nil {
		panic(err)
	}

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

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

	// 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", keyingPair.PublicKey)
	if err != nil {
		panic(err)
	}

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

	encodedExt, err := codec.EncodeToHex(ext)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Ext - %s\n", encodedExt)

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

	err = ext.Sign(keyingPair, options)
	if err != nil {
		panic(err)
	}

	txHash, err := api.RPC.Author.SubmitExtrinsic(ext)
	if err != nil {
		panic(err)
	}
	fmt.Println(txHash.Hex())
}

@cdamian
Copy link
Contributor

cdamian commented Sep 12, 2024

@YuXiaoCoder Please try using the latest version of dynamic extrinsic signing, and by using these extensions when signing in your first example:

err = ext.Sign(
		keyPair,
		meta,
		extrinsic.WithEra(types.ExtrinsicEra{IsImmortalEra: true}, genesisHash),
		extrinsic.WithNonce(types.NewUCompactFromUInt(uint64(accountInfo.Nonce))),
		extrinsic.WithTip(types.NewUCompactFromUInt(0)),
		extrinsic.WithSpecVersion(rv.SpecVersion),
		extrinsic.WithTransactionVersion(rv.TransactionVersion),
		extrinsic.WithGenesisHash(genesisHash),
		extrinsic.WithMetadataMode(extensions.CheckMetadataModeDisabled, extensions.CheckMetadataHash{Hash: types.NewEmptyOption[types.H256]()}),
	)

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

2 participants