How to submit multiple extrinsics in the same block in substrate? (RpcError: 1014: Priority is too low:)

105 Views Asked by At

I created a simple pallet using substrate. I am able to submit extrinsic using the RPC using the substrate-front-end-template.

After submitting the extrinsic, I can see the transaction status as shown below

  1. Current transaction status: Broadcast
  2. Current transaction status: InBlock
  3. ❤️️ Transaction successful! tx hash: 0x808d1a539a9d716203215202d7f9fb7ce10c9696e9449b355ea668871e3e0198 , Block hash: 0x5e95f78444121d0ed46f84d6fa903cac6a5ac58d873c6292a3d73e280f2c75ce

But when I try to submit a new extrinsic while the previous transaction status is Broadcast I am seeing the following error.

Transaction Failed: RpcError: 1014: Priority is too low: (22861 vs 22861): The transaction has too low priority to replace another transaction already in the pool.

I can submit a new extrinsic successfully when the previous transaction is InBlock or successful state.

After digging deeper into why this happens,

I found that each substrate transaction will have two vectors requires and provides. Both contain TransactionTag (vector of bytes). requires is the list of tags to be already present in the ready pool for the current transaction to be included in the block and provides is the list of tags that the current transaction is providing. Transaction

In ready.rs in sc-transaction-pool, when a new transaction is being imported it is clearing the existing transactions which are providing tags that overlap with the provides tags from the current transaction.

I printed the provides tags for the extrinsics I submitted from the UI. When I submit a new extrinsic,

  1. If the previous transaction is in Broadcast state, the provides tag for the new extrinsic is same as the provides tag for previous transaction and I am getting the above error.
  2. If the previous transaction is in InBlock or success state, the provides tag of the new extrinsic is different from provides tag of previous transaction (I guess nonce is changed) and there is no error.

I am guessing when the previous transaction is in Broadcast, the nonce is not updated yet and so the transaction tag. Is there any way to be able to submit new extrinsic even when the previous transaction state is Broadcast?

edit: 2023-11-06

The provides for a transaction is generated by combining the provides created by each of the structs declared here (all of which implement the SignedExtension triat)

pub type SignedExtra = (
    frame_system::CheckNonZeroSender<Runtime>,
    frame_system::CheckSpecVersion<Runtime>,
    frame_system::CheckTxVersion<Runtime>,
    frame_system::CheckGenesis<Runtime>,
    frame_system::CheckEra<Runtime>,
    frame_system::CheckNonce<Runtime>,
    frame_system::CheckWeight<Runtime>,
pallet_asset_conversion_tx_payment::ChargeAssetTxPayment<Runtime>,
);

Among the above structs, only CheckNonce is actually creating provides and requires. That is the only thing that is changed in the transaction tag is the nonce for new transactions which I observed in the logs as well as shown below (the last 4 bytes are changed)

provides: [[212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125, 0, 0, 0, 0]]
provides: [[212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125, 1, 0, 0, 0]]
provides: [[212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125, 2, 0, 0, 0]]

My guess is that the nonce is not updated yet when the transaction is in Broadcast state and is being updated only when the transaction is in InBlock state. Now I am trying to figure out how to update the nonce after submitting the extrinsic so that the provides tag is different for the new extrinsic.

inc_account_nonce method is used to increment the nonce in the runtime storage. But I don't see it being called from anywhere else (apart from test files). inc_account_nonce search

Please feel free to ask any questions or context if not clear.

0

There are 0 best solutions below