Receipt - zoobc/zoobc-core GitHub Wiki
Receipt is an object that act as a proof that nodes communicated. It is received by the sender
(of data, ex: block, transaction, etc) and generated by the receiver
of the data.
Receipt Structure
No | Field | Type | Description |
---|---|---|---|
1 | SenderPublicKey | []byte | The data sender (block/transaction sender) |
2 | RecipientPublicKey | []byte | The data receiver who validate the data it received, and generate the receipt for it |
3 | DataType | uint32 | The type of the data broadcasted by the sender, for now there are [transaction, block] |
4 | DataHash | []byte | The hash of the data sent by the sender |
5 | ReferenceBlockHash | []byte | The recipient latest block's hash |
6 | ReferenceBlockHeight | uint32 | The recipient latest block's height |
7 | ReceiptMerkleRoot | []byte | The latest Receipt Merkle Root if the recipient |
8 | RecipientSignature | []byte | The signature of the [SenderPublicKey, RecipientPublicKey, ReferenceBlockHeight, ReferenceBlockHash, DataType, DataHash, ReceiptMerkleRoot] written in order |
Receipt Types
There are two types of receipt:
-
Linked Receipt
Linked receipt have total 2 value of score.
-
un-linked Receipt
Un-linked receipt have total 0.5 value of score
A receipt is linked
when it can prove a receipt with rmr_linked
value equal to its merkle root value has already been published.
Receipt Collection
Node broadcast data (block, transaction) to collect receipts.
Storing Receipt
Sender Node will need to store the received receipts in a chunk of n
number of receipts in memory, and store to database afterward:
- Collect receipt in memory for size of
n
. (n should be the power of 2) - Build merkle tree and its root once have reach
n
number of receipt. - Store the tree and the root in
receipt_merkle
table, and all receipts will be stored innode_receipt
table with their respective order in the merkle tree.
Data Structure
To store the receipts, we'll have three tables:
node_receipt
, to store node's individual receipt (this will be different across different node)
No | db name | proto name | db type | proto type |
---|---|---|---|---|
1 | sender_public_key | SenderPublicKey | BLOB | []byte |
2 | recipient_public_key | RecipientPublicKey | BLOB | []byte |
3 | data_type | DataType | INTEGER | uint32 |
4 | data_hash | DataHash | BLOB | []byte |
5 | reference_block_height | ReferenceBlockHeight | INTEGER | uint32 |
6 | reference_block_hash | ReferenceBlockHash | BLOB | []byte |
7 | receipt_merkle_root | ReceiptMerkleRoot | BLOB | []byte |
8 | recipient_signature | RecipientSignature | BLOB | []byte |
9 | rmr_index | RMRIndex | INTEGER | uint32 |
merkle_root
, to store the merkle root and its tree of the collected receipt, this value will also be used to be included in the receipt generated by the owner. (this table will also be unique across different node)
node_batch_receipt
, to store the receipt temporarily before building the merkle root and store the receipt in the node_receipt
table, (*we are considering putting this in a kv db)
No | db name | proto name | db type | proto type |
---|---|---|---|---|
1 | sender_public_key | SenderPublicKey | BLOB | []byte |
2 | recipient_public_key | RecipientPublicKey | BLOB | []byte |
3 | data_type | DataType | INTEGER | uint32 |
4 | data_hash | DataHash | BLOB | []byte |
5 | reference_block_height | ReferenceBlockHeight | INTEGER | uint32 |
6 | reference_block_hash | ReferenceBlockHash | BLOB | []byte |
7 | receipt_merkle_root | ReceiptMerkleRoot | BLOB | []byte |
8 | recipient_signature | RecipientSignature | BLOB | []byte |
network_receipt
, to store the receipts published in a block, this table should be identical across different nodes.
Publish Receipt
Node that want to include their receipt in the block they want to publish will need to:
-
Pay attention to the block that may have included one of its own
merkle root
, this will be later used to filter the receipt to be included in a block. -
node will prioritize receipt that can be linked to broadcasted block
rmr (receipt merkle root)
-
on linked receipt, node will need to provide the list of
hashes
needed to proof the validity of the receipt, by:- get the
merkle tree
fromreceipt_merkle
table. - get the least needed number of hashes to proof the validity of the receipt chosen.
- get the
-
if there isn't enough
linked receipt
to provide, node will pick the un-linked receipt (the opposite of linked receipt) to the list.
Published Receipt Validation
-
if linked, validate the receipt and its intermediate hashes against its merkle root
-
if unlinked, give the unlinked score
-
if all the receipt in the block is valid and good to go, store them in
published_receipt
table so that we can link the future receipts to see if thermr
has been published before.