0

I have four transactions which I would like to include in the same block, T1, T2, T3, T4.

There is a race condition so I do not want to broadcast these transactions unless I can be sure they will settle together and in order. This requires running a miner to make this assurance.

Running geth, how could I add four transactions, in order, to my pool so that they will be included if I mine a block but they will not otherwise be broadcast from my machine?

  • If the transactions are sent from the same account, you can get rid of the race conditions by using increasing transaction nonces. Otherwise, one possibility could be to perform the message calls or contract creations with a smart contract. – Briomkez Feb 1 at 15:59
1

In my opinion, this sounds unworkable.

You can't use mining to order transactions favorably in the real world. But, you do have some options.

You can group operations atomically by wrapping in another function. Also, you are assured that transactions that emit from the same EOA will be mined in nonce order. This assurance doesn't mean that someone else can't insert an operation while the state is unsettled, so it's still important to avoid race conditions.

You can use patterns such as Mutex to fight race conditions, but I've yet to encounter a situation that can't be solved without using such measures.

Hope it helps.

  • 2
    To add why mining without broadcasting wouldn't assure ordered, same block processing, assume you mine a block with your 4 transactions in order, and broadcast it. Someone beats you to broadcasting a block at that height though, and yours becomes an uncle. Now, since it's been broadcast but isn't part of the chain, you've essentially broadcast those 4 transactions without mining them. Anyone can put them in a new block, in any order, and even omit some of them – flygoing Feb 1 at 16:21
  • I agree with that. – Rob Hitchens - B9lab Feb 1 at 18:01
  • @flygoing There's a case if transactions have gas price set to 0 gwei then it is very unlikely they will be mined in a new block by another miner. But it still is possible for a malicious miner to mine them in separate blocks. – Ismael Feb 2 at 7:25
1

As a workaround, you could preload a js file that looks for a pattern in certain transactions and start to mine only when all fours are present. For example, if you know all the transaction are from the same address:

var mining_threads = 4;
var txBlock = 0;
var target_address = "0x83c88dbd0059edb45a3e57b9cc50e9ee0fda7190";
var batch = [];
var target_batch = 4;

function waitBatch() {
    if ( eth.getBlock( "pending" ).transactions.length > 0 ) {
        txBlock = eth.getBlock( "pending" ).number
        if ( eth.mining ) return;
        console.log( "  Transactions pending. Search for target" );
        for ( var i = 0; i < eth.getBlock( "pending" ).transactions.length; i++ ) {
            if ( eth.getBlock( "pending" ).transactions[ i ].from == target_address ) {
                batch.push( eth.getBlock( "pending" ).transactions[ i ] );
            }
        }
        if ( batch.length == target_batch ) {
            batch = [];
            miner.start( mining_threads )
        }
        while ( eth.getBlock( "latest" ).number < txBlock + 1 ) {
            if ( eth.getBlock( "pending" ).transactions.length > 0 ) txBlock = eth.getBlock( "pending" ).number;
        }
        console.log( "1 confirmations achieved; mining stopped." );
        miner.stop()
    } else {
        miner.stop()
    }
}
waitBatch();

This is not tested and sure has problems, but that's the idea.
Alternatively, you could edit your sealer in your geth if running a private blockchain, but it's almost always a bad idea.

EDIT
I note you want to keep them in order. You can't. For the vanilla Geth implementation, the commitNewWork() function in worker.go orders in the following way:

//approach 2
transactions := self.eth.TxPool().GetTransactions() <--- fetch from pool
types.SortByPriceAndNonce(transactions)      <---------- order

i.e. Sorts by gas price and nonce value

There are two other approaches in the code which are both commented out, but may give a clue as to previous ideas (or give examples to miners who want to use their own implementation). They are:

approach 1: sort by nonce only approach 3: sort by owner (treating single- and multi-owner transactions differently), then by price and nonce.

You could edit these approaches, if running a private network

  • Thank you this is a great start to get the transactions into the block. If they are sorted by gas price I can control that by choosing the gas price. But does this code ensure that transactions in my pool won't be shared? – William Entriken Feb 2 at 23:55
  • What do you mean with "won't be shared"? You mean you don't want to broadcast the transactions to other nodes? I don't know a way to halt the broadcast of transaction and I guess it's impossible to achieve this preloading a js script. This means you would probably need to start from core/tx_pool.go and edit the go code to don't broadcast transactions or to add a rule to stop the broadcast of a certain type of transactions – waytosay Feb 3 at 1:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.