-
Notifications
You must be signed in to change notification settings - Fork 14
Provenance
Provenance API give user access to
-
key->valuehistory - raw transaction data
- block header data
- transaction existence in block proof
- block(s) existence in ledger proof
// Provenance access to historical data and data integrity proofs
type Provenance interface {
// GetTxProof returns proof that tx with give id is part of blocks merkle tree (path to root)
GetTxProof(txId []byte) (*types.TxProof, error)
// GetBlocksProof returns proof that each block in list of blocks connected to another
// by providing shortest path in skip list between blocks in list
GetBlocksProof(blocks []uint64) (*types.BlockProof, error)
// GetHistory return full history for given key in db
GetHistory(dbName, key string) (HistoryIterator, error)
// GetTransaction returns transaction envelope by its id
GetTransaction(txId []byte) (*types.TransactionEnvelope, error)
// GetBlockHeader returns block header
GetBlockHeader(number uint64) (*types.BlockHeader, error)
// GetLstBlockHeader returns block header of last known block in ledger
GetLastBlockHeader() (*types.BlockHeader, error)
}
type HistoryIterator interface {
Next() (*api.HistoricalData, error)
Close()
}One extra API, to be discussed
// GetSparseBlock returns sparse block, contains only tx visible be user
// and Merkle tree paths for these tx
GetSparseBlock(number uint64) (*types.SparseBlock, error)Based on this API, we can check
- ledger integrity by accessing block headers and validating consistency of ledger merkle list
- with
GetSparseBlock(), even with partial data it returns, we can check past and current database state consistency - transaction existence proof composed of merkle tree path to transaction in block and block existence proof:
GetTxProof()andGetBlocksProof() - block existence proof algorithm described in Transaction-Proofs-Skiplist, proof data accessed using GetBlockProof() API
- proof of active and past states can be done by proving existence of all transactions that caused state changes
- retrieve
key->valuehistory by usingGetHistory()API and provide proofs for all transaction references returned- referenced blocks existence proof in this case can be done by single call to GetBlockProof() with (genesis, history referenced blocks, last block) argument
- retrieve
message TxProof {
BlockHeader header = 1;
repeated bytes path = 2;
}
message BlockProof {
uint64 block_number = 1;
repeated BlockHeader path = 2;
}GetHistory API provides all values of specific keys over time, including references to transactions that change this key.
It is possible form this data, using GetTxProof, GetBlockProof and GetTransactions API, to provide proof of change of specific key at specific time.
As we can see here, the API is Blockchain DB installation level API, not single DB level API and it exposed by DBConnector, but this need to be discussed.
// DBConnector handle connectivity between sdk and Blockchain Database cluster
type DBConnector interface {
...
// GetProvenance returns blockchain db provenance interface
GetProvenance() Provenance
}If not mentioned otherwise, this document describes skip list based proofs for ledger consistency and integrity. For more detailed explanation, see Transaction-Proofs-Skiplist
As mentioned in Transaction document, during provenance data creation phase,
{Key, newValue, BlockTime, BlockNumber, TxTime, TxId, ClientId, IsDelete, IsOk} tuple stored as provenance data for each key in WSet.
GetHistory returns slice of history values based on data stored in provenance tuple
message HistoricalValue {
// DB key
string key = 1;
// Historical value
bytes value = 2;
// Sequencer time when block was created
google.protobuf.Timestamp blocktime = 3;
// Transaction that did the change
bytes txId = 4;
// Block number that holds changing tx
uint64 blocknumber = 5;
// Is this tx deleted this key
bool isDelete = 6;
}For now, we go with the simplest approach - if user now have read access to given key, it can access its historical data as well, even if it didn't has access to this key in the past.
To eliminate difference between client clocks, Transaction time set to be equal to block time. We need to add time to block header.