我来提供一个思路,tron没有nonce的概念,但是有智能合约,这里有个很巧妙的想法,假代码如下
contract walletContract{
struct Call {
address target;
bytes callData;
uint256 nonce;
}
struct Result {
bool success;
bytes returnData;
}
uint256 private nonce;
function tryAggregate(bool requireSuccess, Call[] memory calls) public returns (Result[] memory returnData) {
returnData = new Result[](calls.length);
for(uint256 i = 0; i < calls.length; i++) {
(bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);
if (requireSuccess) {
require(success, "Multicall2 aggregate: call failed");
}
require(calls[i].nonce == nonce,'nonce too low');
nonce++;
returnData[i] = Result(success, ret);
}
}
}
我翻看了tron的发行版本 v4.5.0 Manager.java
// transactions cache linenumber:215
private BlockingQueue<TransactionCapsule> pendingTransactions;
//linenumber 419
if (Args.getInstance().isOpenTransactionSort()) {
this.pendingTransactions = new PriorityBlockingQueue(2000, downComparator);
this.rePushTransactions = new PriorityBlockingQueue<>(2000, downComparator);
} else {
this.pendingTransactions = new LinkedBlockingQueue<>();
this.rePushTransactions = new LinkedBlockingQueue<>();
}
//set the sort order linenumber:1276
trxCap.setOrder(transactionInfo.getFee());
if (!eventPluginLoaded) {
trxCap.setTrxTrace(null);
}
结合官方文档中关于交易生命周期的描述
交易在其生命周期中会依次经历以下几个阶段:
可以初步得到以下结论,理论上是可以取消pending交易的。但是需要节点开启 TransactionSort 及Args.getInstance().isOpenTransactionSort() == true
,排序规则为 TransactionInfo.fee
数值越高越优先。上诉使用合约的自定义nonce的想法本身依赖,进入pending交易之后的节点自身会选择fee更高的交易排在前面,这样之前发送的交易会因为nonce的问题而被 revert。但遗憾的是
Args.getInstance().isOpenTransactionSort()
我并没在官方的配置文件里面找到该字段的配置样例,且该字段配置clear初始值为false。也就是说pending队列初始的时候会是一个LinkedBlockingQueue
不具备优先级的能力。也就是说上面合约的自定nonce的功能是无效的。
没有进一步了解是否可以通过其他的方式开启TransactionSort ,也有可能某些超级节点存在高定制节点的可能性,可以尝试下合约定义nonce的思路。发个100次交易看看取消的成功率。确实在出块太快,交易数量填不满区块的情况下很难取消啊