Skip to content

Tx Origination

uprendis edited this page Mar 25, 2021 · 1 revision

Origination of transactions

In the current implementation of Lachesis, transactions are first sent into a transaction pool (tx pool). This implementation choice is just like the one being used in conventional blockchains (like Bitcoin or Ethereum).

Transaction is called originated when it's included into an event block, check out consensus algorithm. The node that creates the event block containing the transaction is called the transaction's originator.

Conflicting transactions

Unlike conventional blockchains, nodes in Lachesis don't create nor exchange blocks (of the final chain) directly. Instead, transactions are packed into blocks independently based on calculation from events. When a transaction is being originated (included), the validator doesn't yet know exactly the final order which this transaction and some of its previous transactions will be assigned. The final order will be determined by Lachesis consensus engine.

Due to the nature of asynchrony, some originated transactions may fail some checks after they are confirmed, for example, if they conflicted with other transactions from the same sender, or because of occupying tx nonce or insufficient fund to pay the fee. If a confirmed transaction fails to meet the requirements, then transaction gets skipped. Skipped transactions are stored within events but don't get indexed - it's impossible to retrieve them from API by hash, just like if they never were originated. Skipped transactions don't consume sender's fee, but do consume originator's gas power as a penalty for originating a conflicting transaction.

Protection from conflicting transactions

Alice is a transaction (tx) sender, Bob is a validator (originator).

  • Alice sends her transaction into transaction pool (txpool), exactly as she would do it in the eth62 protocol. The transaction gets propagated to all the nodes within period << TxTurnPeriod. Practically, tx should get propagated within ~300ms.
  • When Bob receives the transaction from his txpool, he memorizes the time when he received the transaction as tx arrival time.
    • If tx is within Bob's txpool, then tx has already passed the checks within txpool. It means that tx can be executed correctly on top of a last finalized block (currently known by Bob). It is worth noting that tx will get confirmed not in a next block after a "last finalized block", but not less than after 2 blocks (it's not guaranteed how many blocks will pass due to the asynchrony).
  • Bob calculates transaction's turn hash = sha3(Alice's address, tx.nonce/TxTurnNonces, current epoch number)
  • Bob calculates a deterministic (weighted by stake) permutation of validators against turn hash. The permutation defines the order, in which validators are assigned to originate this tx.
  • Bob calculates the current turn index = ((now - tx arrival time) / TxTurnPeriod) % number of validators
  • Bob calculates the turn index for near future = ((now + TxTurnPeriodLatency - tx arrival time) / TxTurnPeriod) % number of validators
  • If turn index == turn index for near future
    • If it's Bob's turn (i.e. permutated validators[turn index] == Bob)
      • If Bob doesn't know any unconfirmed (but originated) tx from Alice
        • then Bob originates the tx

Mainnet constants:

  • TxTurnNonces = 32
  • TxTurnPeriod = 8 seconds
  • TxTurnPeriodLatency = 1 second

This algorithm implies that Alice's transactions capacity is limited by TxTurnNonces / TTF. If Alice has to send more transactions per second, then she has to send them from multiple addresses.

The chance of originating a conflicting transaction is possible but very low.

The clocks on different validators don't need to match, because relative local time (now - tx arrival time) is used, instead of absolute time.

Reasoning of tx pool

The current Lachesis implementation uses transaction pool (txpool), because it has several advantages over direct submission of transactions into a validator (such method is used by some other DAG aBFT protocols):

  • User (or wallet client) doesn't need to choose a validator, the validators will decide themselves. It makes implementation of a wallet simpler.
  • User doesn't need to know validator's IP to submit the transaction. It allows validator to hide his IP behind sentry nodes as a DoS protection.
  • User doesn't need to re-submit the transaction if chosen validator is offline or failed to originate the transaction. The network itself will assign a different validator after TxTurnPeriod. Hence, it improves the fault tolerance of the transactions submitting.
  • User has no opportunity to secretly send conflicting transactions to multiple validators simultaneously, provoking them to originate conflicting transactions.