Table of Links
-
Append process
4. Append process
4.1 Local append
The append process looks like that:
-
Each new record should have key, value and version fields
-
On append, the algorithm should create hash of record: βππ β = π βπ256(πππ¦, π£πππ’π, π£πππ πππ). This hash brings uniqueness to the record
-
Then algorithm should create partial signature as follow: partialSignature = (privateKey β hash)πππ π, where π is curve parameter.
-
Then algorithm add timestamp and timestamp index to the record. The timestamp β is a timestamp when record is created. The timestamp index is used when concurrency is possible, and two or more records can be created at the same time. In case this happens, all records with the same time have their own index (like 0, 1, 2).
-
Then this record, alongside with hash and signature can be stored locally (for instance in database)
-
This record is called intermediate
4.2 Append from another node
When one node receives new records from another (for instance node A obtained records from node B) during replication process, the append rules vary:
-
The algorithm should validate the record
-
Then algorithm should check, do this node already has this record (it can be done by finding the record by hash).
2.1)If record exist then:
2.1.1) In case received record is multisig and local record is intermediate β then algorithm should replace local intermediate record with received multisig and update the root.
2.1.2) In case local and received records are multisig, then the highest multisig is chosen (the algorithm compares 2 signatures by value) and stored in local record.
2.1.3) In case local record is multisig and received one is intermediate β then algorithm ignore this record (i.e. doesnβt apply) 2.1.4) In case local and received records are intermediate β then algorithm just take signatures from received record (which are not present on local record) and append them to local record.
2.2)if record doesnβt exist:
2.2.1) then algorithm should sign the hash of the received record (like was in local append described above), add it to this record and store
-
Then the algorithm should check if there are enough signatures for multisig (this number is defined by quorum size).
3.1) if yes then:
3.1.1) algorithm build multisig: π πππππ‘π’ππ = β ππππ‘πππππππππ‘π’ππ ππππ π
3.1.2) algorithm build shared public key: π βππππππ’πππππΎππ¦ = β ππ’πππππΎππ¦π β βππ β
3.1.3) algorithm replace intermediate signatures with multisig and sharedPublicKey
3.1.4) algorithm save the record and update the root.
4.3 Record validation
The validation process works as follows:
- First signatures are validated: in case of intermediate signatures
1.1) If signatures are intermediate, then for each intermediate signature the algorithm validate that: ππ’πππππΎππ¦π β βππ β = π πππππ‘π’ππ β πΊ, where G β is a curve parameter (SECP256K1)
1.2)If signature is multisig, then
1.2.1) sharedPublicKey is reconstructed from involved public keys in signature process (the public keys with signatures are stored in record) and compared against received sharedPublicKey. If itβs not equal β then validation is not passed
1.2.2) then multisignature is validated as: ππ’ππ‘πππππππ‘π’ππ β πΊ = π βππππππ’πππππΎππ¦
4.4 State consistency
To make sure, that all nodes have the same sets of records, the root has been introduced. The root is represented as sum of hashes of confirmed records (records with multisig): ππππ‘ = β βππ β π πππ π, where π is a curve parameter. The following formula allows to build the root without order, so technically the append order of hashes doesnβt make any sense in this case. Also, keep in mind, as algorithm has eventual consistency (without rollback option) β we canβt guarantee any ordering.
Also, to make root update quick, the algorithm stores the root on record level:
-
On multisig record insert, the algorithm updates the root by addition of previous root to recordβs hash: ππππ‘ = (ππππ‘ππππ£ + βππ β) πππ π
-
Then this root hash is appended to the record (I call it stateHash)
-
During next append of another new record, there is no need to recalculate the hash root of all records, but we sort confirmed (multisig) records in DESC order by timestamp and timestamp index, and take stateHash from the first record (which is the most recent one)
This approach is also useful for traceability and validation purpose, as all state can be replayed up to any point of history and calculated hash root can be compared with stateHash.
Author:
(1) Egor Zuev ([email protected])
This paper is