Description
Since #1394, we introduce a lock mechanism to improve synchronization of transaction validation by acquiring a lock for a given transaction's hash before transaction's mining.
However, this approach is not perfect in the sense it can create some issue related to the lock alternative (ie. deadlock, timeouts)
This issue aim to provide another approach to be "lock-free" and still insure consistency and synchronization of transaction's validation.
The purpose is to accept multiple parallel transaction's validation, as they could semantically valid.
However, the storage nodes will be able to resolve conflicts to make sure to take a single transaction and
leverage signatures and attestations to ensure consistency to reach a sufficient consensus.
Here it's a workflow representing :
- two transaction's validation for the same address with different data (Tx1' / Tx1'')
- Two set of validations nodes for the given transaction:
- Validation1 for the transaction: Tx1'
- Validation2 for the transaction: Tx1''
- Two set of storage nodes
- Storage25: representing the 25% of the storage nodes which attest transaction
- Storage75: representing the 75% of the storage nodes which attest transaction
sequenceDiagram
Validation1->>+Storage25: ValidateTx(Tx1')
Validation2->>+Storage75: ValidateTx(Tx1'')
Storage75->>+Validation2: AckValid(Tx1'')
Storage25->>+Validation1: AckValid(Tx1')
Validation1->>+Storage25: ReplicateTx(Tx1')
Validation1->>+Storage75: ReplicateTx(Tx1')
Validation2->>+Storage75: ReplicateTx(Tx1'')
Validation2->>+Storage25: ReplicateTx(Tx1')
Storage25->>Storage25: Resolve conflicts (flag to choose tx to commit/already answered)
Note right of Storage25: Priority of conflict resolving: <br />1. Take the longest signature chain <br /> 2.Take first tx's timestamp < 10s drift & not answered <br /> 3. Hash transaction data, sort it and take the first
Storage75->>Storage75: Resolve conflicts (flag to choose tx to commit)
Note right of Storage75: Priority of conflict resolving: <br />1. Take the longest signature chain <br /> 2.Take first tx's timestamp < 10s drift & not answered <br /> 3. Hash transaction data, sort it and take the first
Storage25->>+Validation1: Signature
Storage25->>+Validation2: Signature
Storage75->>+Validation2: Signature
Storage75->>+Validation1: Signature
Validation2->>+Validation2: Enough signatures?
Validation1->>+Validation1: Enough signatures?
Validation2->>+Beacon: Attestation
Validation2->>+Storage75: Attestation
Validation2->>+Storage25: Attestation
Storage75->>+Storage75: Enough signature?
Storage25->>+Storage25: Enough signature?
Storage75->>+Storage75: Store Transaction Tx1'' + Attestation
Storage25->>+Storage25: Remove Tx1' from TransactionPool
Storage25->>+Storage25: Fetch Tx1'' from TransactionPool
Storage25->>+Storage25: Storage Transaction Tx1'' + Attestation
The solution is to use an approach like 3PC (Three Phase Commit) in which ACK, PreCommit, and Commit are used to make sure enough storage nodes are ready to commit something before the real storage of transaction.
This also offers attestation after the commit phase to ensure proof of replication in the transaction's chain.