HTTP_API.md
-
Cédric Moreau authoredCédric Moreau authored
uCoin HTTP API
Contents
Overview
Data is made accessible through an HTTP API mainly inspired from OpenUDC_exchange_formats draft, and has been adapted to fit uCoin specificities.
http[s]://Node[:port]/...
|-- pks/
| |-- add
| |-- all
| `-- lookup
|-- keychain/
| |-- membership
| |-- keyblock
| | `-- [NUMBER]
| `-- current
|-- network/
| |-- parameters
| |-- pubkey
| |-- peering
| | |-- forward
| | |-- status
| | `-- peers/
| | |-- upstream/
| | | `-- [PGP_FINGERPRINT]
| | `-- downstream/
| | `-- [PGP_FINGERPRINT]
| `-- wallet/
| `-- [PGP_FINGERPRINT]
|-- contract/
| |-- parameters
| `-- amendments/
| `-- am/
| `-- [AMENDMENT_NUMBER]
`-- tx/
|-- process
|-- last/
| `-- [count]
|-- sender/
| `-- [PGP_FINGERPRINT]/
| |-- view/
| | `-- [TX_NUMBER]
| `-- last/
| `-- [count]/
| `-- [from]
|-- recipient/
| `-- [PGP_FINGERPRINT]
|-- refering/
| `-- [PGP_FINGERPRINT]/
| `-- [TX_NUMBER]
`-- coins/
|-- list/
| `-- [PGP_FINGERPRINT]
`-- view/
`-- [COIN_ID]/
|-- history
`-- owner
Merkle URLs
Merkle URL is a special kind of URL applicable for resources:
pks/all
network/peering/peers (GET)
network/wallet (GET)
hdc/transactions/sender/[PGP_FINGERPRINT]
hdc/transactions/recipient/[PGP_FINGERPRINT]
Such kind of URL returns Merkle tree hashes informations. In uCoin, Merkle trees are an easy way to detect unsynced data and where the differences come from. For example, network/peers
is a Merkle tree whose leaves are peers' key fingerprint sorted ascending way. Thus, if any new peer is added, a branch of the tree will see its hash modified and propagated to the root hash. Change is then easy to detect.
For commodity issues, this URL uses query parameters to retrieve partial data of the tree, as most of the time all the data is not required. uCoin Merkle tree has a determined number of parent nodes (given a number of leaves), which allows to ask only for interval of them.
Here is an example of members Merkle tree with 5 members (taken from Tree Hash EXchange format (THEX)):
ROOT=H(H+E)
/ \
/ \
H=H(F+G) E
/ \ \
/ \ \
F=H(A+B) G=H(C+D) E
/ \ / \ \
/ \ / \ \
A B C D E
Note: H() is some hash function
Where A,B,C,D,E are already hashed data.
With such a tree structure, uCoin consider the tree has exactly 6 nodes: [ROOT,H,E,F,G,E]
. Nodes are just an array, and for a Lambda Server LS1, it is easy to ask for the values of another server LS2 for level 1 (H
and E
, the second level): it requires nodes interval [1;2]
.
Hence it is quite easy for anyone who wants to check if a Z
member joined the uCoin community as it would alter the E
branch of the tree:
ROOT'=H(H+E')
/ \
/ \
H=H(F+G) E'
/ \ \
/ \ \
F=H(A+B) G=H(C+D) E'=H(E+Z)
/ \ / \ / \
/ \ / \ / \
A B C D E Z
ROOT
changed to ROOT'
, E
to E'
, but H
did not. The whole E'
branch should be updated with the proper new data.
For that purpose, Merkle URL defines different parameters and results:
Parameters
Parameter | Description |
---|---|
leaves |
Defines wether or not leaves hashes should be returned too. Defaults to false . |
leaf |
Hash of a leaf whose content should be returned. Ignore leaves parameter. |
Returns
Merkle URL result with leaves=false
.
{
"depth": 3,
"nodesCount": 6,
"leavesCount": 5,
"root": "6513D6A1582DAE614D8A3B364BF3C64C513D236B"
}
Merkle URL result with leaves=true
.
{
"depth": 3,
"nodesCount": 6,
"leavesCount": 5,
"root": "6513D6A1582DAE614D8A3B364BF3C64C513D236B",
"leaves": [
"32096C2E0EFF33D844EE6D675407ACE18289357D",
"50C9E8D5FC98727B4BBC93CF5D64A68DB647F04F",
"6DCD4CE23D88E2EE9568BA546C007C63D9131C1B",
"AE4F281DF5A5D0FF3CAD6371F76D5C29B6D953EC",
"E0184ADEDF913B076626646D3F52C3B49C39AD6D"
]
}
Merkle URL result with leaf=AE4F281DF5A5D0FF3CAD6371F76D5C29B6D953EC
.
{
"depth": 3,
"nodesCount": 6,
"leavesCount": 5,
"root": "6513D6A1582DAE614D8A3B364BF3C64C513D236B",
"leaf": {
"hash": "AE4F281DF5A5D0FF3CAD6371F76D5C29B6D953EC",
"value": // JSON value (object, string, int, ...)
}
}
uCoin Merkle trees leaves
Each tree manages different data, and has a different goal. Hence, each tree has its own rules on how are generated and sorted tree leaves. Here is a summup of such rules:
Merkle URL | Leaf | Sort |
---|---|---|
pks/all |
Fingerprint of the key | By fingerprint string sort, ascending. |
network/peers (GET) |
Fingerprint of the peer | By fingerprint string sort, ascending. |
network/wallet (GET) |
Fingerprint of the wallet | By fingerprint string sort, ascending. |
hdc/transactions/sender/[PGP_FINGERPRINT] |
Hash of (transaction + signature) | By hash string sort, ascending. |
hdc/transactions/recipient/[PGP_FINGERPRINT] |
Hash of (transaction + signature) | By hash string sort, ascending. |
Unicity
It has to be noted that the first four Merkle URLs, there is no possible conflict for leaves, as every leaf is represents a OpenPGP key whose fingerprint is unique according to uCoin protocol. Indeed: nodes are responsible for the concrete key stored under a fingerprint.
However for the 2 last URLs, conflicts are possible even if largely improbable. Such conflicts would not be a huge problem however: it would lead to hide one of the conflicted transactions, but those 2 URLs are not here for exhaustive inventory of transactions, only for quick synchronization checking. So the goal is still reached.
API
pks/*
This URL is used to manage OpenPGP certificates, making uCoin acting like an SKS server.
pks/add
Goal
POST ASCII-armored OpenPGP certificates.
Parameters
Name | Value | Method |
---|---|---|
keytext |
The raw certificate, ASCII-armored. | POST |
Returns
The sent PGP Public Key and signature.
{
"email":"cem.moreau@gmail.com",
"comment":"udid2;c;CAT;LOL;2000-04-19;e+43.70-079.42;0;",
"name":"LoL Cat",
"fingerprint":"C73882B64B7E72237A2F460CE9CAB76D19A8651E",
"raw":"-----BEGIN PGP PUBLIC KEY BLOCK----- ... -----END PGP PUBLIC KEY BLOCK-----\r\n"
}
pks/lookup
Goal
Allows to search for OpenPGP certificates, according to HKP draft.
Parameters
Name | Value | Method |
---|---|---|
search |
A value for searching in PGP certificates database. May start with '0x' for direct search on PGP fingerprint. | GET |
op |
Operation: may be either 'index' or 'get'. | GET |
Returns
A list of matching PGP keys in json format if op=index
, a single ASCII-armored key if op=get
.
{
"keys": [
{
"signature": "-----BEGIN PGP SIGNATURE-----\r\n ... -----END PGP SIGNATURE-----\r\n",
"key":
{
"email":"cem.moreau@gmail.com",
"comment":"udid2;c;CAT;LOL;2000-04-19;e+43.70-079.42;0;",
"name":"LoL Cat",
"fingerprint":"C73882B64B7E72237A2F460CE9CAB76D19A8651E",
"raw":"-----BEGIN PGP PUBLIC KEY BLOCK----- ... -----END PGP PUBLIC KEY BLOCK-----\r\n"
}
},{
"signature": "-----BEGIN PGP SIGNATURE-----\r\n ... -----END PGP SIGNATURE-----\r\n",
"key":
{
"email":"cem.moreau@gmail.com",
"comment":"udid2;c;CAT;LOL;2000-04-19;e+43.70-079.42;0;",
"name":"LoL Cat",
"fingerprint":"C73882B64B7E72237A2F460CE9CAB76D19A8651E",
"raw":"-----BEGIN PGP PUBLIC KEY BLOCK----- ... -----END PGP PUBLIC KEY BLOCK-----\r\n"
}
}
]
pks/all
Goal
Merkle URL refering all the received public keys.
Parameters
None.
Returns
Merkle URL result.
{
"depth": 3,
"nodesCount": 6,
"leavesCount": 5,
"root": "114B6E61CB5BB93D862CA3C1DFA8B99E313E66E9"
}
Merkle URL leaf: public key
{
"hash": "2E69197FAB029D8669EF85E82457A1587CA0ED9C",
"value": {
"fingerprint": "C73882B64B7E72237A2F460CE9CAB76D19A8651E",
"pubkey": "-----BEGIN PGP PUBLIC KEY BLOCK----- ... -----END PGP PUBLIC KEY BLOCK-----\r\n"
}
}
keychain/*
parameters
Goal
GET the keychain parameters used by this node.
Parameters
None.
Returns
The synchronization parameters.
{
"sigDelay": 157680000,
"sigValidity": 31536000,
"sigQty": 5,
"stepMax": 3,
"powZeroMin": 4,
"powPeriod": 10
}
Parameters meaning is described under Protocol parameters.
keychain/membership
Goal
POST a Membership document.
Parameters
Name | Value | Method |
---|---|---|
membership |
The raw membership structure. | POST |
signature |
The signature of the membership parameter. |
POST |
Returns
The posted membership request + posted signature.
{
"signature": "-----BEGIN PGP SIGNATURE-----\r\n ... -----END PGP SIGNATURE-----\r\n",
"membership": {
"version": "1",
"currency": "beta_brousouf",
"issuer": "FD17FECBAF731658EDEB60CF8700174B1D585861",
"membership": "IN",
"sigDate": 1390739944,
"raw": "Version: 1\r\n...Membership: IN\r\n"
}
}
keychain/keyblock
Goal
POST a new keyblock to add to the keychain.
Parameters
Name | Value | Method |
---|---|---|
keyblock |
The raw keyblock to be added | POST |
signature |
Signature of the raw keyblock | POST |
Returns
The promoted keyblock if successfuly added to the keychain (see keyblock/[number] return object).
keychain/keyblock/[NUMBER]
Goal
GET the promoted keyblock whose number NUMBER
.
Parameters
Name | Value | Method |
---|---|---|
NUMBER |
The promoted keyblock number (integer value) we want to see. | URL |
Returns
The promoted keyblock if it exists (otherwise return HTTP 404).
{
"version": 1,
"nonce": 28,
"number": 1,
"timestamp": 1408996317,
"membersCount": 4,
"currency": "beta_brousouf",
"membersRoot": "E9A2E7146E00CF407CE7C837CD83430327928CA9",
"signature": "-----BEGIN PGP SIGNATURE-----...-----END PGP SIGNATURE-----\r\n",
"hash": "0000F40BDC0399F2E84000468628F50A122B5F16",
"previousHash": "0009A7A62703F976F683BBA500FC0CB832B8220D",
"previousIssuer": "C73882B64B7E72237A2F460CE9CAB76D19A8651E",
"membersChanges": [],
"keysChanges": [
{
"membership": {
"signature": "iQGcBAABCAA...J8/UODEA==\n=t2S+\n",
"membership": "1:33BBFC0C67078D72AF128B5BA296CC530126F372:IN:1408995911:Snowy (udid2;c;SNOW;JOHN;1980-07-13;e+40.71-074.01;0;)
<john.snow@got.com>"
},
"certpackets": "wsBfBBAB...LWPztzla5vwADMow==\n",
"keypackets": "xsDNBFH...oEA=\n",
"fingerprint": "33BBFC0C67078D72AF128B5BA296CC530126F372",
"type": "N"
},
{
"membership": {
"signature": "iQEcBAAB...3NGiw=\n=2nmK\n",
"membership": "1:663A65AC3CE8F36DCBBCAF7ABD4367024C29635E:IN:1408995912:Superman (udid2;c;KENT;CLARK-JOSEPH;1950-04-07;e+37.31-083.34;0;)
<superman@krypton.com>"
},
"certpackets": "wsBfB...aWdNJL1VaYk=\n",
"fingerprint": "663A65AC3CE8F36DCBBCAF7ABD4367024C29635E",
"type": "N"
},
{
"keypackets": "",
"certpackets": "wsDfBBAB...zcBmO\n",
"fingerprint": "C73882B64B7E72237A2F460CE9CAB76D19A8651E",
"type": "U"
},
{
"keypackets": "",
"certpackets": "wsDfBBAB...KyKG5SymM7YQ==\n",
"fingerprint": "2E69197FAB029D8669EF85E82457A1587CA0ED9C",
"type": "U"
}
]
}
keychain/current
Same as keyblock/[number], but return last accepted keyblock.
network/*
This URL is used for uCoin Gossip protocol (exchanging UCG messages).
network/pubkey
Goal
GET the public key of the peer.
Parameters
None.
Returns
The public key in ASCII-armored format.
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.12 (GNU/Linux)
mQENBFHHC/EBCADWTLSN7EGP+n30snndS3ZNcB02foL+0opcS6LK2coPDJLg2noo
keJRHZxF3THmZQrKwZOjiuDBinOc5DWlzIS/gD/RaXwntgPFlGKBlBU+g255fr28
ziSb5Y1lW4N//nUFdPZzoMmPgRj0b17T0UPCoMR8ZZ/Smk5LINbQwt+A+LEoxEdE
Vcq+Tyc0OlEabqO6RFqiKDRiPhGPiCwVQA3yPjb6iCp5gTchObCxCnDbxA0Mfj9F
mHrGbepNHGXxStO4xT0woCb7y02S1E8K08kOc5Bq9e1Yj5I/mdaw4Hn/Wp28lZl1
mnO1u1z9ZU/rcglhEyaEOTwasheb44QcdGSfABEBAAG0TUxvTCBDYXQgKHVkaWQy
O2M7Q0FUO0xPTDsyMDAwLTA0LTE5O2UrNDMuNzAtMDc5LjQyOzA7KSA8Y2VtLm1v
cmVhdUBnbWFpbC5jb20+iQE9BBMBCAAnBQJRxwvxAhsDBQkLR5jvBQsJCAcDBRUK
CQgLBRYCAwEAAh4BAheAAAoJEOnKt20ZqGUeZYcH/0ItH4b/O0y7V1Jzc1DZAdn4
iDiI7/SF3fN4f6cJCu/SOVb+ERFIb6JK+HNHdVAcMHKaPW625R0FahHUkcXWkkGm
Q6+sLIsVZwVN1oeZtlD12cq9A4UJyfJUXkinMKkI8xpdV8J7s5wFRavOS/qaF5be
ah0Z+IGwQK0nuXxWpT6UZWbpUfXPQB2Mz2/rpjSWKwO3X4FwwOfDiuZExyH2JPDY
shdPcj/x+gnzYW9XfWCJw3rOK42vtM+aLtUpJO0Jh6X/sj/iqyS4rPB4DVCmEgSX
Px1P+kqnsz3aNTOIujXS8Faz+TC+eNhn+z3SoTl5gBlNNM171fWFr0BR3nIfIu65
AQ0EUccL8QEIAPAQaxK6s4DjDHiOwrMotvb479QD5PsHU6S0VG0+naoPlNJb2d5w
YhnFAn4aYLiXx4IIl38rHnV+yWATOUe2rdCe4enTXkxyWJVaxIcNJLFpUjHYGbrC
nNwiXpuQfSDuRN/wcVNSBKXhWNUPY9IsbgERWhS5YTFnuQcBjMqDwF6JImQ8O4nZ
wno811nqK1XaMuLVvXZAsO1Vi1k3NArM5+jdlq9e3BA0NcHJmGEcQdTw0Tk5Oq6r
mE8ux7pS0bn6OUkkseR5DyRlFtzqi4wp30GeggeFExx7ZCVuctpJX9ZoC3cJoZT0
s3LuUtV0EW50yCtP+3Vpkek2WtjfVbM6kDkAEQEAAYkBJQQYAQgADwUCUccL8QIb
DAUJC0eY7wAKCRDpyrdtGahlHg7+B/95xEoSrFQ7/mc7g6sbisvx3s547gUXXYSu
FHS03IMDWJrfGKqXtBf9ETBx4OLeBXY7z1lL4WCN6/xtrL+mSQ9dbDqdXv/1EhkS
v0s+IvJ34KYGAkFXSCoTE7rnkPwQjoMYVSFkf5e8g9adyKvndq/QSPNuv+FPL6sH
m1N9nmus5Ebr0zTVDmmfoqzokuDfHm5h6YrkFscMGjrCKWuXSiTaGj9Hm3MqeZ3T
Kva5isa/h0h7Ai3wJ5XJpMrFNN6BU/wIt7fM2hsNAOwaG+WUfgjYEkOua8gPPtpL
ZJJPb/89yrs9F7JkLi/oiAl5VpItm+hlFpLe1TE7oa6k53eZ2a+V
=rOj9
-----END PGP PUBLIC KEY BLOCK-----
network/peering
Goal
GET the peering informations of this node.
Parameters
None.
Returns
Peering entry of the node.
{
"version": "1",
"currency": "beta_brousouf",
"fingerprint": "A70B8E8E16F91909B6A06DFB7EEF1651D9CCF468",
"endpoints": [
"BASIC_MERKLED_API some.dns.name 88.77.66.55 2001:0db8:0000:85a3:0000:0000:ac1f 9001",
"BASIC_MERKLED_API some.dns.name 88.77.66.55 2001:0db8:0000:85a3:0000:0000:ac1f 9002",
"OTHER_PROTOCOL 88.77.66.55 9001",
],
"signature": "-----BEGIN PGP SIGNATURE-----\r\n ... -----END PGP SIGNATURE-----\r\n"
}
network/peering/peers (GET)
Goal
Merkle URL refering to peering entries of every node inside the currency network.
Parameters
None.
Returns
Merkle URL result.
{
"depth": 3,
"nodesCount": 6,
"leavesCount": 5,
"root": "114B6E61CB5BB93D862CA3C1DFA8B99E313E66E9"
}
Merkle URL leaf: peering entry
{
"hash": "2E69197FAB029D8669EF85E82457A1587CA0ED9C",
"value": {
"version": "1",
"currency": "beta_brousouf",
"fingerprint": "A70B8E8E16F91909B6A06DFB7EEF1651D9CCF468",
"endpoints": [
"BASIC_MERKLED_API some.dns.name 88.77.66.55 2001:0db8:0000:85a3:0000:0000:ac1f 9001",
"BASIC_MERKLED_API some.dns.name 88.77.66.55 2001:0db8:0000:85a3:0000:0000:ac1f 9002",
"OTHER_PROTOCOL 88.77.66.55 9001"
],
"signature": "-----BEGIN PGP SIGNATURE-----\r\n ... -----END PGP SIGNATURE-----\r\n"
}
}
network/peering/peers (POST)
Goal
POST a UCG peering entry document to this node in order to alter UCG peering table.
Parameters
Name | Value | Method |
---|---|---|
entry |
UCG peering entry document. | POST |
signature |
Signature of the UCG entry's value. | POST |
Returns
The posted entry.
{
"version": "1",
"currency": "beta_brousouf",
"fingerprint": "A70B8E8E16F91909B6A06DFB7EEF1651D9CCF468",
"endpoints": [
"BASIC_MERKLED_API some.dns.name 88.77.66.55 2001:0db8:0000:85a3:0000:0000:ac1f 9001",
"BASIC_MERKLED_API some.dns.name 88.77.66.55 2001:0db8:0000:85a3:0000:0000:ac1f 9002",
"OTHER_PROTOCOL 88.77.66.55 9001"
],
"signature": "-----BEGIN PGP SIGNATURE-----\r\n ... -----END PGP SIGNATURE-----\r\n"
}
network/peering/peers/upstream
Goal
GET a list of peers this node is listening to for ANY incoming transaction.
Parameters
None.
Returns
The corresponding peer list's fingerprints.
{
"peers": [
"A70B8E8E16F91909B6A06DFB7EEF1651D9CCF468",
"B356F8A6AD4A0431AF047AA204511A9F8A51ED37"
]
}
network/peering/peers/upstream/[PGP_FINGERPRINT]
Goal
GET a list of peers this node is listening to for incoming transactions of PGP_FINGERPRINT
.
Parameters
Name | Value | Method |
---|---|---|
PGP_FINGERPRINT |
PGP key's fingerprint whose incoming transactions are listened by this node. | URL |
Returns
The corresponding peer list.
{
"peers": [
"A70B8E8E16F91909B6A06DFB7EEF1651D9CCF468",
"B356F8A6AD4A0431AF047AA204511A9F8A51ED37"
]
}
network/peering/peers/downstream
Goal
GET a list of peers this node is listened by for ANY incoming transaction.
Parameters
None.
Returns
The corresponding peer list.
{
"peers": [
"A70B8E8E16F91909B6A06DFB7EEF1651D9CCF468",
"B356F8A6AD4A0431AF047AA204511A9F8A51ED37"
]
}
network/peering/peers/downstream/[PGP_FINGERPRINT]
Goal
GET a list of peers this node is listened by for incoming transactions of PGP_FINGERPRINT
.
Parameters
Name | Value | Method |
---|---|---|
PGP_FINGERPRINT |
PGP key's fingerprint whose incoming transactions are listened by other nodes. | URL |
Returns
The corresponding peer list.
{
"peers": [
"A70B8E8E16F91909B6A06DFB7EEF1651D9CCF468",
"B356F8A6AD4A0431AF047AA204511A9F8A51ED37"
]
}
network/peering/forward
Goal
POST a UCG forward document to this node in order to be sent back incoming transactions.
Parameters
Name | Value | Method |
---|---|---|
forward |
UCG forward document. | POST |
signature |
Signature of the UCG forward document. | POST |
Returns
The posted forward.
{
"version": "1",
"currency": "beta_brousouf",
"from": "A70B8E8E16F91909B6A06DFB7EEF1651D9CCF468",
"to": "CC5AE6DA4307AD2339FB52013119E9704EDE0802",
"forward": "KEYS",
"keys": [
"395DF8F7C51F007019CB30201C49E884B46B92FA",
"58E6B3A414A1E090DFC6029ADD0F3555CCBA127F",
"4DC7C9EC434ED06502767136789763EC11D2C4B7",
"8EFD86FB78A56A5145ED7739DCB00C78581C5375",
"95CB0BFD2977C761298D9624E4B4D4C72A39974A"
]
}
network/peering/status
Goal
POST a UCG status document to this node in order notify of its status.
Parameters
Name | Value | Method |
---|---|---|
status |
UCG status document. | POST |
signature |
Signature of the UCG entry's value. | POST |
Returns