Introduction
Since we want to deprecate BMA, it’s time to think about what should replace it. I’m writing this draft to suggest a first API. Please let me know what you think, what is missing, or what could be done better. Obviously, it has been written from my point of view and my experience in the development of Sakia, and we need the experience of everyone to write the future of BMA.
Duniter Ecosystem
As you know, there are two types of clients in Duniter ecosystem :
- Naive clients : These clients trust a given node and only one node. It trusts the administrator of the node. In case of cheating or in case of a bug, the client can be mistaken. The advantage of this behaviour is that the client is really smooth and fast. It doesn’t consume too much bandwith, and is compatible with small ressources endpoints.
- Simplified Verification clients : These clients trust the data they get because they request many nodes. They requests nodes identified by an identity, and as such, they are not sybillizable. The advantage of this behaviour is safety : the client request any data against multiple nodes. If one is cheating or buggy, its data wont match the data of other nodes. In such a case, this data will be ignored
The problem with current API (Basic Merkled API) is that it’s not really merklized When you require data, you can only get every things, to its smallest details. The consequence is that when you need to verify data, you can only request it again and again against multiple nodes, resulting in endless loading like below :
Requirements for a new API
This new API would make a full usage of Merkle Trees to verify data. As such, every data needs to have its associated merkled tree, to simplify verification against multiple nodes.
Identities data
These datas are requested for a given triplet of [uid/pubkey/blockstamp].
The data we need when we request Identity informations are :
- Its signature
- Its blockchain state : written or not-written
- Its revokation state : revoked or not revoked
- If revoked :
- at which block
- at which timestamp
- If revoked :
- Its distance state : outdistanced or not
- Its sentry state : sentry or not
- Its membership state : if a document was sent, which one (IN or OUT)
- If IN document
- at which block
- at which timestamp
- If IN document
Certifications received data
These datas are requested for a given triplet of [uid/pubkey/blockstamp].
The data we need when we request Certifications informations are :
- Its issuer data :
- UID
- Pubkey
- Blockstamp
- Signature
- Member or not
- Its issuance state :
- at which block
- at which timestamp
- Its written state : written or not
- if written :
- at which block
- at which timestamp
- if written :
Certifications sent data
These datas are requested for a given triplet of [uid/pubkey/blockstamp].
The data we need when we request Certifications informations are :
- Its receiver data :
- UID
- Pubkey
- Blockstamp
- Signature
- Its issuance state :
- at which block
- at which timestamp
- Its written state : written or not
- if written :
- at which block
- at which timestamp
- if written :
Transactions received data
These datas are requested for a given [pubkey]. It should be possible to use it with a given [address] too.
The data we need when we request Transactions history are :
- The raw document
- The signature
- The written state : written or not
- if written :
- at which block
- at which timestamp
Transactions sent data
These datas are requested for a given [pubkey].
The data we need when we request Transactions history are :
- The raw document
- The signature
- The written state : written or not
- if written :
- at which block
- at which timestamp
UDTXO (Unspent Dividend or Transaction Outputs Data)
These datas are requested for a given [pubkey]. It should be possible to use it with a given [address] too.
The data we need when we request Avalaible outputs are :
- The type of output (Dividend or Transaction)
- The index of the output (Block number or Index in TX document)
- The identifier of the output (Pubkey or TxHash)
- The amount of the output (int)
- The base of the output (int)
Blockchain data
These datas are requested for a given block range [from]/[to]. The data we need when we request the blockchain are :
- The block number
- The block hash
- The block raw document
- The block signature
Network data
With the arrival of WS2P, Network data is not necessarily handled by this API.
Requests and answers proposal
Requests process
- The client sends a “Data Request” to a given node. It gets its answer, formed as a tree of data.
- The client builds the Merkled Tree corresponding to this tree
- The client send a “Verification request” to N given nodes. The verification request returns the root of the merkle tree.
- The client compares the Root received by the verification nodes to the one he built, and validate or unvalidate the data
These requests can be done in parallel. They should be sent to nodes that are on the same blockchain HEAD.
Verification only concerns written state of data. Validity of the data can be insured thanks to hashes and signatures.
General form of the requests
- The requests should be done using JSON HTTP
- The URI should distinguish :
- The type of data requested
- The source of data : from the pools or from the blockchain. Data from the pools cannot be verified using a merkle tree : there are not guarantees that they are the same on every nodes.
- Filters (range, uid, pubkey, blockstamp, txhash…)
- The type of request (Data request or Verification)
API proposal
State requests
These requests have a merkle tree associated. They should be used to verify the state of a given data.
They can be used on data in the blockchain or in the pool, as below :
- If the data is found in the blockchain, its
written
field has a value and the hash is computed depending on this value - If the data is found in the pool, its
written
field is empty. The hash is the hash of an empty string :e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
- If the data is not found, it returns a 404
Transaction state
/transaction/[data|verify]/[txhash]
: Returns the transaction associated to a given tx hash.
Available parameters :
raw: True or False. If True, returns the transaction document and its signature in the results.
Data :
{
data: {
written: {
blockstamp: [Blockstamp],
timestamp: [Timestamp]
}
},
raw: {
document: [String],
signature: [String]
}
}
Verification :
{
result: Hash([BlockstampHash],[TimestampHash])
}
Certification state
/certification/[data|verify]/[certHash]
: Returns the certification associated to a given hash
Available parameters :
raw: True or False. If True, returns the transaction document and its signature in the results.
state: True or False. If True, returns the issuing identity state in the answer
issuance: True or False. If True, returns the certification issuance date in the answer
Data :
{
data: {
identity: {
uid: [str],
pubkey: [str],
blockstamp: [str],
signature: [str],
},
state: {
member: [bool]
}
issuance: {
blockstamp: [Blockstamp],
timestamp: [int]
},
written: {
blockstamp: [Blockstamp],
timestamp: [int]
},
},
raw: {
document: [String],
signature: [String]
}
}
Verification :
{
result: Hash(
Hash(Hash(member))?,
Hash(Hash(issuance.blockstamp, issuance.timestamp))?,
Hash(Hash(written.blockStamp, written.timestamp))
)
}
Identity state
/identity/[data|verify]/[uid]/[pubkey]/[blockstamp]
: Returns the identity data
Available parameters :
raw: True or False. If True, returns the identity document and its signature in the results.
state: True or False. If True, returns the full identity state details the answer
issuance: True or False. If True, returns the certification issuance date in the answer
Data :
{
data: {
state: {
member: [bool],
"revocation": {
"blockstamp": [Blockstamp],
"timestamp": [int],
"signature": [str]
"written": {
"blockstamp": [Blockstamp],
"timestamp": [int],
}
}
"expired": [bool],
"outdistanced": [bool],
"sentry": [bool]
}
issuance: {
blockstamp: [Blockstamp],
timestamp: [int]
},
written: {
blockstamp: [Blockstamp],
timestamp: [int]
},
},
raw: {
document: [String],
signature: [String]
}
}
Verification :
{
result: Hash(
Hash(Hash(member),
Hash(Hash(revocation.blockstamp),
Hash(revocation.timestamp),
Hash(revocation.signature)
Hash(Hash(revocation.written.blockstamp),
Hash(revocation.written.timestamp))?
)?,
Hash(expired),
Hash(outdistanced),
Hash(sentry)),
Hash(Hash(issuance.blockstamp),Hash(issuance.timestamp)),
Hash(Hash(written.blockstamp),Hash(written.timestamp))
)
}
Data list requesting
UDTXO list
/udtxo/[data|verify]/[pubkey|address]
: Returns the UDTXO for a given pubkey or address. Filters the data using from and to parameters.
Available parameters :
pool: True or False. If True, returns also the UDTXO available in the pool of the node
Data :
{
data: [
{
"type": [D or T],
"noffset": [int],
"identifier": [identifier],
"amount": [int],
"conditions": [str],
"base": [int]
},
{
...
},
]
Verification :
{
result: Hash(UDTXO (Pool excluded))
}
Transactions lists
/txhistory/[data|verify]/[pubkey|address]
: Returns the transaction history for a given pubkey or address. Filters the data using from and to parameters.
Blockchain lists
/blockchain/[data|verify]/[from]/[to]
: Returns the blocks for a given range between [from] and [to].
Available parameters :
raw: True or False. If True, returns also the raw block documents
Data :
{
data: [
{
number: [int],
hash: [str],
issuer: [str],
signature: [str]
raw: [str]
}
]
Verification :
{
result: BlockHash([to])
}