precedence brings secure blockchain-powered traceability features to your already existing legacy information system!
precedence is the first open source ledger allowing non blockchain specialist to put in place a transparent, immutable, and cryptographically verifiable transaction log with a minimum effort and fully integrated to their existing database or file system.
precedence is compliant with multiple data sources:
- file system
- SQL databases
- noSQL databases
- stream processing
By connecting your data source to precedence you automatically get:
- proof-of-existence on every data connected;
- proof-of-ownership compliant with your PKI;
- automatic versioning system for every pieces of information.
All these features allow you bring secure blockchain-powered traceability features to your legacy information system.
precedence is agnostic to the data type considered and can be use to bring immutable and undeniable traceability to every data that you already operate in your information system. Your system is most likely already compliant and there is no need to apply modification to it to start using precedence.
precedence is edited by inBlocks so you can rely on us for hosting the solution for you, supporting you during the deployment and providing you a very strong SLA.
In the following:
- "fingerprint" means "hexadecimal string format for the hash computed with SHA-256 algorithm";
- "obfuscated fingerprint of <VALUE>" means fingerprint of "<SEED> <VALUE>".
-
a Redis version 5+ instance. If you don't have one, you can launch a container that will host a redis instance (not part of a cluster, not replicated, not scalable so not production-compliant). To do so you can run one of the following ways:
- without persistence
docker run --rm --name redis -p 6379:6379 \ redis:alpine redis-server --appendonly no --save ""
- with persistence, detached in background
docker run -d --name redis -p 6379:6379 \ -v $HOME/precedence-redis:/data \ redis:alpine redis-server --appendonly yes --appendfsync always # remove container docker rm -f redis # remove data rm -rf $HOME/precedence-redis
-
If you don't use Docker: Node.js version 10.18.1+ and npm version 6.13.4+.
-
From npm (coming soon)
-
From Docker
# usage docker run --rm inblocks/precedence --help # run docker run --rm --name precedence \ --link redis -p 9000:9000 \ -e PRECEDENCE_PRIVATE_KEY=5962a8486b88c88d14e16a18fd1bbc0207603d84f9cd6434b477baa88da40200 \ inblocks/precedence --redis redis:6379
-
From GitHub sources
git clone https://github.com/inblocks/precedence.git cd precedence for module in api cli common core; do echo "$module" (cd "$module" && npm i) done for module in api cli; do (cd "$module" && npm link) done # usage precedence-api --help # run export PRECEDENCE_PRIVATE_KEY=5962a8486b88c88d14e16a18fd1bbc0207603d84f9cd6434b477baa88da40200 precedence-api
Make sure the api
environment variable is the API endpoint you want to use.
api="http://localhost:9000"
To create a first record you can use the following command. By default the original data is not stored in precedence, the only data-related information stored is its fingerprint.
curl -XPOST -H "Content-Type: application/octet-stream" "$api/records?pretty=true" -d "value 1"
You will find below a response example.
{
"took": 38,
"status": 201,
"data": {
"provable": {
"id": "5c89750b07bced2dbaa5d16eb46826fe3f06297cf5f930defe7169158b24fd9d",
"seed": "bdec0dd5015e69d32ec8fd8a868ac44e0962ea64320e109ab48d789eab6b4421",
"hash": "3de8d12c829a8e06ffeabac575aa3852f90d57160767832d6bdfde44bb3cc116",
"chains": {},
"previous": [],
"address": "0d80666da65ba73600a4c7c8615ede83ac12914b54d0411127c26cdb22180596",
"signature": "14592d327fdd14f4c851ce67f49c13b8b39792ac09c90b9ebda3b6ab47f82454"
},
"timestamp": 1586943700854,
"seed": "d86323c48bbc83e658420137d368cbcaa68ad3db060a8f52e6fa328d818675b1",
"hash": "65da867639080176b5998c77219e2745474aa518a04268522467322f06fbd9d9",
"chains": {},
"address": "0x4592350babefcc849943db091b6c49f8b86f8aaa",
"signature": "0xcc8bfb566fe89bdc2b6bfce1e35886cda7cf790492b117f12696eeb8ce5bcd3278c7c43cdfcda56e82c70064d7fd02ecbdc3c73caad0a7371136b491c8b44a201b"
}
}
For sure you need some explanation about the returned JSON response:
took
is the number of millisecond this request needed to be processed at server-side;status
is the HTTP status code;data
contains every piece of information related to the original data you provided;provable
contains the information that you will be able to prove using precedence;id
is the record identifier;seed
is the obfuscated fingerprint of the rootseed
;hash
is the obfuscated fingerprint of the roothash
;chains
is the rootchains
but where keys and values are the obfuscated fingerprint of their original value;previous
is the list of the record identifiers that are directly linked to this record;address
is the obfuscated fingerprint of rootaddress
;signature
is the obfuscated fingerprint of rootsignature
;
timestamp
is the record creation time (EPOCH millisecond);seed
is the random data used for obfuscation;hash
is the fingerprint of the original data;chains
is the map of relation between a chain and its last record identifier;address
is used for proof-of-ownership, corresponding to the public key of ECDSA key pair used to sign the roothash
;signature
is the Ethereum signature of the roothash
.
We can check that:
- the obfuscated fingerprint of
seed
value is equal toprovable.seed
value:
echo -n 'd86323c48bbc83e658420137d368cbcaa68ad3db060a8f52e6fa328d818675b1 d86323c48bbc83e658420137d368cbcaa68ad3db060a8f52e6fa328d818675b1' | sha256sum
- the obfuscated fingerprint of the hash is equal to
provable.hash
value:
echo -n "d86323c48bbc83e658420137d368cbcaa68ad3db060a8f52e6fa328d818675b1 $(echo -n 'value 1' | sha256sum | cut -d' ' -f1)" | sha256sum
- the signature is valid with https://etherscan.io/verifiedSignatures:
- [Step 1] Address:
0x4592350babefcc849943db091b6c49f8b86f8aaa
; - [Step 2] Message Signature Hash:
0xcc8bfb566fe89bdc2b6bfce1e35886cda7cf790492b117f12696eeb8ce5bcd3278c7c43cdfcda56e82c70064d7fd02ecbdc3c73caad0a7371136b491c8b44a201b
; - [Step 3] Enter the original message that was signed:
65da867639080176b5998c77219e2745474aa518a04268522467322f06fbd9d9
; - Verify:
Message Signature Verified
.
- [Step 1] Address:
Let's create another record with the store=true
parameter.
curl -XPOST -H "Content-Type: application/octet-stream" "$api/records?pretty=true&store=true" -d "value 2"
{
"took": 13,
"status": 201,
"data": {
"provable": {
"id": "4cb00e1268a32986728731d9c4f83aaa24cb5131393f33471d9110decb6c526f",
"seed": "1e597254c89c2e825707f74020f792b4733cbfda0dcebb076fbd3bc6a8751a73",
"hash": "b1b5c148fe52f7eb614cf40758d02b01643f77c6fae1e0831af2bb29445599e7",
"chains": {},
"previous": [],
"address": "9d219de6f76888eadbac06969e1d1b52bf771bccf2a07e55522abc5a0387877f",
"signature": "236f41335cd6e35d628415a5c2763d3417b225f4de676c1174b1730c30d8ea55"
},
"timestamp": 1586943700998,
"seed": "6311318358a71afe79d42f5044c513aa59a2d3fc47c1551a9f880011cfda9806",
"hash": "e0a44d3c544c8895dacc7c32952766ee4db44122af955826e45c9486639ef5e4",
"chains": {},
"address": "0x4592350babefcc849943db091b6c49f8b86f8aaa",
"signature": "0xbcb94922257b69fb5bf7bee76be9110100b569290e234b580f6ca8a96af477c37708eaf951ad2032bd3f9c453dc4d74e0db03cd554356ef95baccf4ea0ea0d801b",
"data": {
"bytes": 7
}
}
}
You can see that you have persisted 7 bytes in precedence (data.bytes
field).
To retrieve the original data you can run:
curl -XGET "$api/records/4cb00e1268a32986728731d9c4f83aaa24cb5131393f33471d9110decb6c526f?data=true"
Let's create the same original data again.
curl -XPOST -H "Content-Type: application/octet-stream" "$api/records?pretty=true&store=true" -d "value 2"
{
"took": 8,
"status": 201,
"data": {
"provable": {
"id": "0459bfbde0852a6574284482f706a8f4bcd26c1047a5d3bbeed284dbb73a2f2e",
"seed": "1cf9aaee273120fd4c9de4bd9040bf3b64bcc68cffb7167c454db9d8c51d8065",
"hash": "536ad2b899d70e897a2ad9cae290aa79f489c09b7ad9a7834352a9c9c083040b",
"chains": {},
"previous": [],
"address": "af96cbebaba4d0f4d6134f7f8183bef3b7a7dee27a1d2217fa237fd7431b8da5",
"signature": "91d47d00b94dd32520e7c86f31a2357fcdd56216b182ee553f1a21108d4e731c"
},
"timestamp": 1586943701116,
"seed": "2b2632c048053aaa2bdaf199c639e9050b9fbfbf548b06641fbf8bc35d06a605",
"hash": "e0a44d3c544c8895dacc7c32952766ee4db44122af955826e45c9486639ef5e4",
"chains": {},
"address": "0x4592350babefcc849943db091b6c49f8b86f8aaa",
"signature": "0xbcb94922257b69fb5bf7bee76be9110100b569290e234b580f6ca8a96af477c37708eaf951ad2032bd3f9c453dc4d74e0db03cd554356ef95baccf4ea0ea0d801b",
"data": {
"bytes": 7
}
}
}
All the values of the provable
object are different from the previous one, even with the same original data. This is made possible by using the seed
in the hashing process. This way the provable
fields are 100% obfuscated and can not lead to data leaking.
It is possible to provide the fingerprint of the original data with the hash
parameter.
curl -XPOST -H "Content-Type: application/octet-stream" "$api/records?pretty=true&hash=5e2d78eb5107622b5441f53ac317fe431cebbfc2a04036c4ed820e11d54d6d1c" -d "value 3"
{
"took": 11,
"status": 201,
"data": {
"provable": {
"id": "c62c73727112c371e0d453841fdcd4d71f2ddce548d8d886262a00fadcd9a512",
"seed": "88e0778d377e593caa834a03247802d1ac196a2e41e33cfab4a457200441d0e1",
"hash": "8fea85b172453ce2cd109accd2efcdd07a1685a6b9a9d851e8e426a079ed417b",
"chains": {},
"previous": [],
"address": "804455fcdc3e008c7d409d231fb560cab9da9d201d0316c0e7726d73cec2cf76",
"signature": "ec48f624958158894361938feaee33811c058552ef46df489a446cd47470ce9f"
},
"timestamp": 1586943701152,
"seed": "1c737d77a1a1f6788fa56e7f1512139be4ef85addc04a9d7612e1f4ee536c9f4",
"hash": "5e2d78eb5107622b5441f53ac317fe431cebbfc2a04036c4ed820e11d54d6d1c",
"chains": {},
"address": "0x4592350babefcc849943db091b6c49f8b86f8aaa",
"signature": "0x33d5ba51b98e9956d813a52fe53ea726cf77877d38180f8a1754e077771b9a71465f4dd657d5a165a491cefa5663b2339e5dd82540e17c8df965d7350781d8361c"
}
}
By doing so the received data fingerprint is compared to the provided one to make sure that the received data has not be altered by the network.
It is also possible to provide a fingerprint without the original data.
curl -XPOST "$api/records?pretty=true&hash=085a57ddb929d1a2853aad31940d6e718918762b8db43f299e86fe732d13d6b9"
{
"took": 10,
"status": 201,
"data": {
"provable": {
"id": "1ed9397b7ef55c4ec84596d3cd7ff775ec1e31e56498b423cd1912241d970612",
"seed": "310b8391c69ba61d43672aef252140e19c527a9018661d17ae13ff2e41dc4474",
"hash": "077c43d8ea09ba50ec30b7a0c74a9da1e695ba8725370d7db9edb857cb047da6",
"chains": {},
"previous": [],
"address": "8d693ec12733f8b079e44c638b31cfbbac0dcbdb0ba8d22ade1dccfbf0a8a0fe",
"signature": "462eea0293eeb51788936239ed6eae2348c39e8c4be91ff53b3419b48b603427"
},
"timestamp": 1586943701190,
"seed": "5a1673706a0c4fb099e3bbb4e2e72c0e66d92d463aba9fc284d9f79dc0201e68",
"hash": "085a57ddb929d1a2853aad31940d6e718918762b8db43f299e86fe732d13d6b9",
"chains": {},
"address": "0x4592350babefcc849943db091b6c49f8b86f8aaa",
"signature": "0x0335865798e357d8dbe4a851f387e2f091be6eca16d3909711a0450eb030323a12cf602f31b1635add36f2bd67a4bd5a49e175ac86c828b811a06c30c49b3fc21c"
}
}
You can specify an identifier for your record. This identifier must be unique and so can not be attached to any other record.
curl -XPOST -H "Content-Type: application/octet-stream" "$api/records?pretty=true&store=true&id=E518B4BB-2668-4ED7-B9E3-E63803BCAC93" -d "value 5"
{
"took": 8,
"status": 201,
"data": {
"provable": {
"id": "3a31d56747785fafe73bc6745a1d21c6b8c38d14b7573fa3fe30745aded1e2c4",
"seed": "678df6dc906cbf3599971d6c1585a9dff9e6c3b8df95822784bc7e3444b0a132",
"hash": "52d33422efcc497f309303a144d135b439987586f37cd6577e8db697a4c1d232",
"chains": {},
"previous": [],
"address": "1f82be94e382b93683c1ca0a769c089b47cd77ab131f624cc99cc5a02c9d3d7e",
"signature": "10468cf3496cbb83ced1ef83bf474b3e48f0dc6e6a6ed37b01575d447272cc99"
},
"timestamp": 1586943701220,
"seed": "ec3a8c0439c1127e243ee780a043ed2f4635e83ed4176967e3a7c92664a18f5b",
"hash": "3db104a9dc47163e43226d0b25c4cabf082d1813a80d4d217b75a9c2b1e49ae8",
"chains": {},
"address": "0x4592350babefcc849943db091b6c49f8b86f8aaa",
"signature": "0x7c6d80cf86f8c5b096d1761eaedb9835896c0ccd839722d4197b268ba8e7c568154bf8bf701ba689dd68e5d8f3f7528d721c35ca87e79021a447587f2966d0c61b",
"data": {
"bytes": 7
}
}
}
The returned identifier is the fingerprint of the identifier you provided.
If you try to create a new record with the same identifier you will get an error.
curl -XPOST -H "Content-Type: application/octet-stream" "$api/records?pretty=true&id=E518B4BB-2668-4ED7-B9E3-E63803BCAC93" -d "value 6"
{
"took": 14,
"status": 409,
"error": 3,
"message": "Record \"3a31d56747785fafe73bc6745a1d21c6b8c38d14b7573fa3fe30745aded1e2c4\" already exists"
}
To read a record you can use its identifier.
curl -XGET "$api/records/3a31d56747785fafe73bc6745a1d21c6b8c38d14b7573fa3fe30745aded1e2c4?pretty=true"
{
"took": 5,
"status": 200,
"data": {
"provable": {
"id": "3a31d56747785fafe73bc6745a1d21c6b8c38d14b7573fa3fe30745aded1e2c4",
"seed": "678df6dc906cbf3599971d6c1585a9dff9e6c3b8df95822784bc7e3444b0a132",
"hash": "52d33422efcc497f309303a144d135b439987586f37cd6577e8db697a4c1d232",
"chains": {},
"previous": [],
"address": "1f82be94e382b93683c1ca0a769c089b47cd77ab131f624cc99cc5a02c9d3d7e",
"signature": "10468cf3496cbb83ced1ef83bf474b3e48f0dc6e6a6ed37b01575d447272cc99"
},
"timestamp": 1586943701220,
"seed": "ec3a8c0439c1127e243ee780a043ed2f4635e83ed4176967e3a7c92664a18f5b",
"hash": "3db104a9dc47163e43226d0b25c4cabf082d1813a80d4d217b75a9c2b1e49ae8",
"chains": {},
"address": "0x4592350babefcc849943db091b6c49f8b86f8aaa",
"signature": "0x7c6d80cf86f8c5b096d1761eaedb9835896c0ccd839722d4197b268ba8e7c568154bf8bf701ba689dd68e5d8f3f7528d721c35ca87e79021a447587f2966d0c61b",
"data": {
"bytes": 7
}
}
}
To create a new block you can run the following command. To know more about block management check the dedicated block
documentation section below.
curl -XPOST "$api/blocks?pretty=true"
{
"took": 71,
"status": 201,
"data": {
"index": 0,
"root": "27d046333217d2be772104530c9414c2a52557a647c0e08d5de75df58babb3f7",
"timestamp": 1586943701382,
"count": 6,
"previous": null
}
}
The block is created, you can now get the record again and retrieve additional information.
curl -XGET "$api/records/3a31d56747785fafe73bc6745a1d21c6b8c38d14b7573fa3fe30745aded1e2c4?pretty=true"
{
"took": 10,
"status": 200,
"data": {
"provable": {
"id": "3a31d56747785fafe73bc6745a1d21c6b8c38d14b7573fa3fe30745aded1e2c4",
"seed": "678df6dc906cbf3599971d6c1585a9dff9e6c3b8df95822784bc7e3444b0a132",
"hash": "52d33422efcc497f309303a144d135b439987586f37cd6577e8db697a4c1d232",
"chains": {},
"previous": [],
"address": "1f82be94e382b93683c1ca0a769c089b47cd77ab131f624cc99cc5a02c9d3d7e",
"signature": "10468cf3496cbb83ced1ef83bf474b3e48f0dc6e6a6ed37b01575d447272cc99"
},
"timestamp": 1586943701220,
"seed": "ec3a8c0439c1127e243ee780a043ed2f4635e83ed4176967e3a7c92664a18f5b",
"hash": "3db104a9dc47163e43226d0b25c4cabf082d1813a80d4d217b75a9c2b1e49ae8",
"chains": {},
"address": "0x4592350babefcc849943db091b6c49f8b86f8aaa",
"signature": "0x7c6d80cf86f8c5b096d1761eaedb9835896c0ccd839722d4197b268ba8e7c568154bf8bf701ba689dd68e5d8f3f7528d721c35ca87e79021a447587f2966d0c61b",
"data": {
"bytes": 7
},
"block": {
"index": 0,
"root": "27d046333217d2be772104530c9414c2a52557a647c0e08d5de75df58babb3f7",
"timestamp": 1586943701382,
"proof": [
"f8f1a0bd5899e48994c46a329293df3172c87b9fbeb7e00162853374e084fd6c84d0b7a0c3c89fb568dd8598863d425ccaa3a1d7f849aa6cb3ccab4252eaf95f35af88e680a0f3c9402a787aea94c8bd00c4defc8efbefd98068857e2adad249c2f31fef6b08a008e422578242318ccd5c7a744dc71591ca7eb7353afd137bdc24142152a17718a0c180669fa0d9bdc79037bc05d6c010cc94fe377eadd4fd1e4c526ef0f94ee3b780a03e82c6d1f7c885d3f25002da12e87e4c7d8713bf84104111de545eb0161f15db80808080a0029b7d37a85f21e8a6d1610954b28b59872ddd1500fff7fab92936b1dafcfc5280808080",
"f842a03a31d56747785fafe73bc6745a1d21c6b8c38d14b7573fa3fe30745aded1e2c4a03e7c863c5363eb0de037e7d7e535e3a4a5d7e227e17d5b8da02257c43236199e"
]
}
}
}
The returned document contains information related to the block the record belongs to.
To check the proof, see the dedicated open-source project precedence-proof.
You can delete the data that is stored in the record. The record itself can not be deleted because it would cause chain inconsistency, same thing for the hash of the data, but the data itself is not required to keep the chain consistent.
curl -XDELETE "$api/records/3a31d56747785fafe73bc6745a1d21c6b8c38d14b7573fa3fe30745aded1e2c4?pretty=true"
{
"took": 7,
"status": 200,
"data": {
"bytes": 7
}
}
The record data has been deleted releasing 7
bytes, let's retrieve this record again.
curl -XGET "$api/records/3a31d56747785fafe73bc6745a1d21c6b8c38d14b7573fa3fe30745aded1e2c4?pretty=true"
{
"took": 5,
"status": 200,
"data": {
"provable": {
"id": "3a31d56747785fafe73bc6745a1d21c6b8c38d14b7573fa3fe30745aded1e2c4",
"seed": "678df6dc906cbf3599971d6c1585a9dff9e6c3b8df95822784bc7e3444b0a132",
"hash": "52d33422efcc497f309303a144d135b439987586f37cd6577e8db697a4c1d232",
"chains": {},
"previous": [],
"address": "1f82be94e382b93683c1ca0a769c089b47cd77ab131f624cc99cc5a02c9d3d7e",
"signature": "10468cf3496cbb83ced1ef83bf474b3e48f0dc6e6a6ed37b01575d447272cc99"
},
"timestamp": 1586943701220,
"seed": "ec3a8c0439c1127e243ee780a043ed2f4635e83ed4176967e3a7c92664a18f5b",
"hash": "3db104a9dc47163e43226d0b25c4cabf082d1813a80d4d217b75a9c2b1e49ae8",
"chains": {},
"address": "0x4592350babefcc849943db091b6c49f8b86f8aaa",
"signature": "0x7c6d80cf86f8c5b096d1761eaedb9835896c0ccd839722d4197b268ba8e7c568154bf8bf701ba689dd68e5d8f3f7528d721c35ca87e79021a447587f2966d0c61b",
"block": {
"index": 0,
"root": "27d046333217d2be772104530c9414c2a52557a647c0e08d5de75df58babb3f7",
"timestamp": 1586943701382,
"proof": [
"f8f1a0bd5899e48994c46a329293df3172c87b9fbeb7e00162853374e084fd6c84d0b7a0c3c89fb568dd8598863d425ccaa3a1d7f849aa6cb3ccab4252eaf95f35af88e680a0f3c9402a787aea94c8bd00c4defc8efbefd98068857e2adad249c2f31fef6b08a008e422578242318ccd5c7a744dc71591ca7eb7353afd137bdc24142152a17718a0c180669fa0d9bdc79037bc05d6c010cc94fe377eadd4fd1e4c526ef0f94ee3b780a03e82c6d1f7c885d3f25002da12e87e4c7d8713bf84104111de545eb0161f15db80808080a0029b7d37a85f21e8a6d1610954b28b59872ddd1500fff7fab92936b1dafcfc5280808080",
"f842a03a31d56747785fafe73bc6745a1d21c6b8c38d14b7573fa3fe30745aded1e2c4a03e7c863c5363eb0de037e7d7e535e3a4a5d7e227e17d5b8da02257c43236199e"
]
}
}
}
The data
field has been removed from the response and if you try to get the original data, you'll get an error.
curl -XGET "$api/records/3a31d56747785fafe73bc6745a1d21c6b8c38d14b7573fa3fe30745aded1e2c4?pretty=true&data=true"
{
"took": 3,
"status": 404,
"error": 5,
"message": "Record \"3a31d56747785fafe73bc6745a1d21c6b8c38d14b7573fa3fe30745aded1e2c4\" data not found"
}
To create a record as a new state of an existing record you should use the previous
parameter. It allows you to link you records with each other.
curl -XPOST -H "Content-Type: application/octet-stream" "$api/records?pretty=true&id=61E51581-7763-4486-BF04-35045DC7A0D3&store=true&previous=3a31d56747785fafe73bc6745a1d21c6b8c38d14b7573fa3fe30745aded1e2c4" -d "value 6"
{
"took": 9,
"status": 201,
"data": {
"provable": {
"id": "75bdb5a188a281c9576331b5573d5be50f7802d92cc591d9dbbbfbcb7ee42de6",
"seed": "59e4b259d7884bafff084fd92f97eb35e81637ba90c6aba39d86edc9b7adc11c",
"hash": "abc4912f67a96da20ae8edb134940de466a876883444bd55392a350f505e927d",
"chains": {},
"previous": [
"3a31d56747785fafe73bc6745a1d21c6b8c38d14b7573fa3fe30745aded1e2c4"
],
"address": "be9d4cbdce2e2fdbea4633916ea5da817a7506d06dd7a0c77f35e02576b2bc58",
"signature": "c378e410f054b897373cafb25fb8c78af6305dc5f344402be8acbd26304b2085"
},
"timestamp": 1586943701559,
"seed": "2e7537ac999c154f26c1f6db680a74d85c702773d0f244c30262bcf6ce2a7c02",
"hash": "5b193ff1cf8ac2f1aabe5fe7de85debb29e8f337bc89b135a590c1073800cf80",
"chains": {},
"address": "0x4592350babefcc849943db091b6c49f8b86f8aaa",
"signature": "0xa6bbc4cc1e50088492dc482801c4d4695d14f367b3b10e34f93a962e1a8213b634b7bfa6a95edc6bbc25a359cf9a4554d6dee72078a671f401b6aa667dcb1ab31c",
"data": {
"bytes": 7
}
}
}
The previous
field contains the parameter you provided. This parameter must be the identifier that was returned at creation time, you can not use your own identifier to link your records. If you want to link your record based on a label that you control, use the chain parameter (this is explain in the chain section below).
The chain API calls have been designed to facilitate the record insertion and the creation of links (using the previous
field) between those records.
To insert a record in the precedence system by using the chain method you need to use the chain
parameter.
curl -XPOST -H "Content-Type: application/octet-stream" "$api/records?pretty=true&id=4FF6B617-F1CF-4F10-A314-4C7733A9DB7F&chain=chain1" -d "value 7"
{
"took": 11,
"status": 201,
"data": {
"provable": {
"id": "893f0b2b05ed0013789be0dfa521575f243d083c5a2654c60f948eef1ce9b951",
"seed": "1a31577411c9d2113b456f93cc4f02dd3e46d761ddfa19ca2520a3a8356b05c6",
"hash": "270b1dfc6a533a92eccf40c954ff69be7bf73b46ad34610022791db5f445b036",
"chains": {
"046b8f5c3838f00a01c1d74a1f0edbf5c084964e871d0df54cdb6c0bd1dfb567": null
},
"previous": [],
"address": "ed2fd552ae271c9f1f62fea0340b5ff46963b85858e19553258e5ace706ff377",
"signature": "ccac82540eebab148a1d655c59819898502218f422b33c75b5c10a69a94ea5b7"
},
"timestamp": 1586943701595,
"seed": "f340b962dec300ff7dd176d92aed6450a77003a3d03b73f01cb57d180425c5a6",
"hash": "ed914881e913845413125b682876d976b9eab7335980726ddc59f785beb4d5ad",
"chains": {
"chain1": null
},
"address": "0x4592350babefcc849943db091b6c49f8b86f8aaa",
"signature": "0xa1d9b27cb9cbcdda4172a373ef4e82f13f193d837e2e21b760685d099354ef7a7e3250470af7e33ffe6b77aa27b0d509b00e311917249a022abf4cc8469506751b"
}
}
The field chains
contains information about the chain state at insertion time. In this scenario the chain chain1
was never used before so this newly created record is the first and the last record of this chain. Because there was no record in this chain the value set in chain.chain1
is null
. When the chain exists, the inserted record is appended behind the last record of the chain specified in the parameter chain
. In the same time, and in a atomic way, the newly inserted record become the last record of the chain and can be refered to using the chain1
label.
Let's insert a second record using this chain1
label.
curl -XPOST -H "Content-Type: application/octet-stream" "$api/records?pretty=true&chain=chain1&store=true" -d "value 8"
{
"took": 14,
"status": 201,
"data": {
"provable": {
"id": "44d2fd22cebf91d4375260ae12565afa83cf18f24873f956728166c603091dd3",
"seed": "94a98a2a30ad41832bf524a0ea1ece7c5dee015a785910d7dbbab30226715c3a",
"hash": "88d7d782931a525b9c9e9438fe2d46b5c6b45e7dd843e06fa4468617b4946c33",
"chains": {
"75e7db6f4670f1a2f71e4bbf758d3d2bc30ad8c3e52b82f5dc89e93199728b4d": "893f0b2b05ed0013789be0dfa521575f243d083c5a2654c60f948eef1ce9b951"
},
"previous": [
"893f0b2b05ed0013789be0dfa521575f243d083c5a2654c60f948eef1ce9b951"
],
"address": "e1f40d966cb211c7a886a73c28b1c336e8549dc76e217f95dd7bebc39217fd79",
"signature": "db8e0af1c6e3718804b9d06805b66e5dc467b345535dd7eddbde8b8f1bfe5180"
},
"timestamp": 1586943701636,
"seed": "f7a2f7002e8729ccceb374db92822431126f8583fb3358a08136eddf14e8db1c",
"hash": "1bb1c73103ef6ae888ab45afa617f8ec63f21bf959a284363d7a83055ac4f87d",
"chains": {
"chain1": "893f0b2b05ed0013789be0dfa521575f243d083c5a2654c60f948eef1ce9b951"
},
"address": "0x4592350babefcc849943db091b6c49f8b86f8aaa",
"signature": "0x13f6c3fbc6513cd9dbeca59878613ea10f2356bf5fcc75d15b8993ceb5cb56156b11668c316505ba817f8ab2a0edb24b555de3442865ee336f0b9f3cad8634ae1b",
"data": {
"bytes": 7
}
}
}
The field chains
contains the key chain1
whose value is the record identifier of the previously inserted record. The record has been appended at the end of the chain and the label chain1
now refers to the newly inserted record. This information is provable because it is part of the record definition. The key stored in provable.chains
has been obfuscated to avoid any data leak. chains.chain1
can be removed by deleting the entire chain.
We can check that:
- the obfuscated fingerprint of
chain1
is equal to75e7db6f4670f1a2f71e4bbf758d3d2bc30ad8c3e52b82f5dc89e93199728b4d
:
echo -n "f7a2f7002e8729ccceb374db92822431126f8583fb3358a08136eddf14e8db1c chain1" | sha256sum
- the
chains.chain1
value is equal to theprovable.chains.75e7db6f4670f1a2f71e4bbf758d3d2bc30ad8c3e52b82f5dc89e93199728b4d
value:893f0b2b05ed0013789be0dfa521575f243d083c5a2654c60f948eef1ce9b951
.
To retrieve the record currently refered by a chain name (i.e. the last record of the chain), you can use the following API call:
curl -XGET "$api/chains/chain1?pretty=true"
{
"took": 2,
"status": 200,
"data": {
"provable": {
"id": "44d2fd22cebf91d4375260ae12565afa83cf18f24873f956728166c603091dd3",
"seed": "94a98a2a30ad41832bf524a0ea1ece7c5dee015a785910d7dbbab30226715c3a",
"hash": "88d7d782931a525b9c9e9438fe2d46b5c6b45e7dd843e06fa4468617b4946c33",
"chains": {
"75e7db6f4670f1a2f71e4bbf758d3d2bc30ad8c3e52b82f5dc89e93199728b4d": "893f0b2b05ed0013789be0dfa521575f243d083c5a2654c60f948eef1ce9b951"
},
"previous": [
"893f0b2b05ed0013789be0dfa521575f243d083c5a2654c60f948eef1ce9b951"
],
"address": "e1f40d966cb211c7a886a73c28b1c336e8549dc76e217f95dd7bebc39217fd79",
"signature": "db8e0af1c6e3718804b9d06805b66e5dc467b345535dd7eddbde8b8f1bfe5180"
},
"timestamp": 1586943701636,
"seed": "f7a2f7002e8729ccceb374db92822431126f8583fb3358a08136eddf14e8db1c",
"hash": "1bb1c73103ef6ae888ab45afa617f8ec63f21bf959a284363d7a83055ac4f87d",
"chains": {
"chain1": "893f0b2b05ed0013789be0dfa521575f243d083c5a2654c60f948eef1ce9b951"
},
"address": "0x4592350babefcc849943db091b6c49f8b86f8aaa",
"signature": "0x13f6c3fbc6513cd9dbeca59878613ea10f2356bf5fcc75d15b8993ceb5cb56156b11668c316505ba817f8ab2a0edb24b555de3442865ee336f0b9f3cad8634ae1b",
"data": {
"bytes": 7
}
}
}
You can insert a record by setting multiple chain
and previous
parameters.
curl -XPOST -H "Content-Type: application/octet-stream" "$api/records?pretty=true&chain=chain1&chain=chain2&previous=893f0b2b05ed0013789be0dfa521575f243d083c5a2654c60f948eef1ce9b951&previous=75bdb5a188a281c9576331b5573d5be50f7802d92cc591d9dbbbfbcb7ee42de6&store=true" -d "value 9"
{
"took": 12,
"status": 201,
"data": {
"provable": {
"id": "0003275d55e40c7346d3acc97ee13ef85470f4a032bea1589cc58261e9e04a0e",
"seed": "c5d4a6550a6417a8d13df0dbab50f155b5a7b749021a047da8536616fbfe7f94",
"hash": "c446b788f9c626f330b860517384128b04229474d7347fb9a91415325117b2f6",
"chains": {
"ff528be20fae1d8ea812c5ddc7971fef91e49ab5e0010a73b7f2fb07681d135c": "44d2fd22cebf91d4375260ae12565afa83cf18f24873f956728166c603091dd3",
"5c0a63a2536835f10b1f4f470fc2a0d158c4342a2f0e16e988486e306f6de6c6": null
},
"previous": [
"44d2fd22cebf91d4375260ae12565afa83cf18f24873f956728166c603091dd3",
"75bdb5a188a281c9576331b5573d5be50f7802d92cc591d9dbbbfbcb7ee42de6",
"893f0b2b05ed0013789be0dfa521575f243d083c5a2654c60f948eef1ce9b951"
],
"address": "9bff8f93b42b1f7dc49ab0fb93e1d685106814492211db7a2a111bc67dd0a683",
"signature": "48a0c1bf6630406288d8c36d2828113f22a151bd0eb52fdd4746ea8014382088"
},
"timestamp": 1586943701803,
"seed": "8867c4a328f630be32cd9624ad9ec51e0d2190c6bf91177778264185659c860f",
"hash": "52d11cc7df0271d87bdd6c70e17a8a1ea878ac96dd9c0a8d5860df87cefbdb8e",
"chains": {
"chain1": "44d2fd22cebf91d4375260ae12565afa83cf18f24873f956728166c603091dd3",
"chain2": null
},
"address": "0x4592350babefcc849943db091b6c49f8b86f8aaa",
"signature": "0x9512cf941a081db411960054d00a204e0cde97f34c477576b50aa21be15d43c04ac1f514babd0be4b7f39123e8594da32caf527e5a4aeed316e65ad570c9a1b41b",
"data": {
"bytes": 7
}
}
}
In this case the precedence server computes at insertion time and in a atomic way the previous record(s) of this newly inserted record. It uses the chain parameters to get the list of the previous records, it merges this set to the set defined using the previous
parameter. This atomic operation also make sure that this record is considered as the last record of the chains that have been set as parameter.
The previous inserted record is the last records on both chain1
and chain2
. Let's try to retrieve the records refered by chain chain1
and chain chain2
to compare the result.
curl -XGET "$api/chains/chain1?pretty=true"
{
"took": 3,
"status": 200,
"data": {
"provable": {
"id": "0003275d55e40c7346d3acc97ee13ef85470f4a032bea1589cc58261e9e04a0e",
"seed": "c5d4a6550a6417a8d13df0dbab50f155b5a7b749021a047da8536616fbfe7f94",
"hash": "c446b788f9c626f330b860517384128b04229474d7347fb9a91415325117b2f6",
"chains": {
"ff528be20fae1d8ea812c5ddc7971fef91e49ab5e0010a73b7f2fb07681d135c": "44d2fd22cebf91d4375260ae12565afa83cf18f24873f956728166c603091dd3",
"5c0a63a2536835f10b1f4f470fc2a0d158c4342a2f0e16e988486e306f6de6c6": null
},
"previous": [
"44d2fd22cebf91d4375260ae12565afa83cf18f24873f956728166c603091dd3",
"75bdb5a188a281c9576331b5573d5be50f7802d92cc591d9dbbbfbcb7ee42de6",
"893f0b2b05ed0013789be0dfa521575f243d083c5a2654c60f948eef1ce9b951"
],
"address": "9bff8f93b42b1f7dc49ab0fb93e1d685106814492211db7a2a111bc67dd0a683",
"signature": "48a0c1bf6630406288d8c36d2828113f22a151bd0eb52fdd4746ea8014382088"
},
"timestamp": 1586943701803,
"seed": "8867c4a328f630be32cd9624ad9ec51e0d2190c6bf91177778264185659c860f",
"hash": "52d11cc7df0271d87bdd6c70e17a8a1ea878ac96dd9c0a8d5860df87cefbdb8e",
"chains": {
"chain1": "44d2fd22cebf91d4375260ae12565afa83cf18f24873f956728166c603091dd3",
"chain2": null
},
"address": "0x4592350babefcc849943db091b6c49f8b86f8aaa",
"signature": "0x9512cf941a081db411960054d00a204e0cde97f34c477576b50aa21be15d43c04ac1f514babd0be4b7f39123e8594da32caf527e5a4aeed316e65ad570c9a1b41b",
"data": {
"bytes": 7
}
}
}
curl -XGET "$api/chains/chain2?pretty=true"
{
"took": 1,
"status": 200,
"data": {
"provable": {
"id": "0003275d55e40c7346d3acc97ee13ef85470f4a032bea1589cc58261e9e04a0e",
"seed": "c5d4a6550a6417a8d13df0dbab50f155b5a7b749021a047da8536616fbfe7f94",
"hash": "c446b788f9c626f330b860517384128b04229474d7347fb9a91415325117b2f6",
"chains": {
"ff528be20fae1d8ea812c5ddc7971fef91e49ab5e0010a73b7f2fb07681d135c": "44d2fd22cebf91d4375260ae12565afa83cf18f24873f956728166c603091dd3",
"5c0a63a2536835f10b1f4f470fc2a0d158c4342a2f0e16e988486e306f6de6c6": null
},
"previous": [
"44d2fd22cebf91d4375260ae12565afa83cf18f24873f956728166c603091dd3",
"75bdb5a188a281c9576331b5573d5be50f7802d92cc591d9dbbbfbcb7ee42de6",
"893f0b2b05ed0013789be0dfa521575f243d083c5a2654c60f948eef1ce9b951"
],
"address": "9bff8f93b42b1f7dc49ab0fb93e1d685106814492211db7a2a111bc67dd0a683",
"signature": "48a0c1bf6630406288d8c36d2828113f22a151bd0eb52fdd4746ea8014382088"
},
"timestamp": 1586943701803,
"seed": "8867c4a328f630be32cd9624ad9ec51e0d2190c6bf91177778264185659c860f",
"hash": "52d11cc7df0271d87bdd6c70e17a8a1ea878ac96dd9c0a8d5860df87cefbdb8e",
"chains": {
"chain1": "44d2fd22cebf91d4375260ae12565afa83cf18f24873f956728166c603091dd3",
"chain2": null
},
"address": "0x4592350babefcc849943db091b6c49f8b86f8aaa",
"signature": "0x9512cf941a081db411960054d00a204e0cde97f34c477576b50aa21be15d43c04ac1f514babd0be4b7f39123e8594da32caf527e5a4aeed316e65ad570c9a1b41b",
"data": {
"bytes": 7
}
}
}
We can see that both requests return the same result, both chains have the same the last record.
To delete a chain, the label not the blockchain itself, you can run the following command:
curl -XDELETE "$api/chains/chain1?pretty=true"
{
"took": 3,
"status": 200,
"data": {
"id": "0003275d55e40c7346d3acc97ee13ef85470f4a032bea1589cc58261e9e04a0e"
}
}
The response gives you the last record id.
curl -XGET "$api/chains/chain1?pretty=true"
{
"took": 1,
"status": 404,
"error": 7,
"message": "Chain \"chain1\" not found"
}
curl -XGET "$api/chains/chain2?pretty=true"
{
"took": 2,
"status": 200,
"data": {
"provable": {
"id": "0003275d55e40c7346d3acc97ee13ef85470f4a032bea1589cc58261e9e04a0e",
"seed": "c5d4a6550a6417a8d13df0dbab50f155b5a7b749021a047da8536616fbfe7f94",
"hash": "c446b788f9c626f330b860517384128b04229474d7347fb9a91415325117b2f6",
"chains": {
"ff528be20fae1d8ea812c5ddc7971fef91e49ab5e0010a73b7f2fb07681d135c": "44d2fd22cebf91d4375260ae12565afa83cf18f24873f956728166c603091dd3",
"5c0a63a2536835f10b1f4f470fc2a0d158c4342a2f0e16e988486e306f6de6c6": null
},
"previous": [
"44d2fd22cebf91d4375260ae12565afa83cf18f24873f956728166c603091dd3",
"75bdb5a188a281c9576331b5573d5be50f7802d92cc591d9dbbbfbcb7ee42de6",
"893f0b2b05ed0013789be0dfa521575f243d083c5a2654c60f948eef1ce9b951"
],
"address": "9bff8f93b42b1f7dc49ab0fb93e1d685106814492211db7a2a111bc67dd0a683",
"signature": "48a0c1bf6630406288d8c36d2828113f22a151bd0eb52fdd4746ea8014382088"
},
"timestamp": 1586943701803,
"seed": "8867c4a328f630be32cd9624ad9ec51e0d2190c6bf91177778264185659c860f",
"hash": "52d11cc7df0271d87bdd6c70e17a8a1ea878ac96dd9c0a8d5860df87cefbdb8e",
"chains": {
"chain1": "44d2fd22cebf91d4375260ae12565afa83cf18f24873f956728166c603091dd3",
"chain2": null
},
"address": "0x4592350babefcc849943db091b6c49f8b86f8aaa",
"signature": "0x9512cf941a081db411960054d00a204e0cde97f34c477576b50aa21be15d43c04ac1f514babd0be4b7f39123e8594da32caf527e5a4aeed316e65ad570c9a1b41b",
"data": {
"bytes": 7
}
}
}
curl -XGET "$api/records/75bdb5a188a281c9576331b5573d5be50f7802d92cc591d9dbbbfbcb7ee42de6?pretty=true"
{
"took": 2,
"status": 200,
"data": {
"provable": {
"id": "75bdb5a188a281c9576331b5573d5be50f7802d92cc591d9dbbbfbcb7ee42de6",
"seed": "59e4b259d7884bafff084fd92f97eb35e81637ba90c6aba39d86edc9b7adc11c",
"hash": "abc4912f67a96da20ae8edb134940de466a876883444bd55392a350f505e927d",
"chains": {},
"previous": [
"3a31d56747785fafe73bc6745a1d21c6b8c38d14b7573fa3fe30745aded1e2c4"
],
"address": "be9d4cbdce2e2fdbea4633916ea5da817a7506d06dd7a0c77f35e02576b2bc58",
"signature": "c378e410f054b897373cafb25fb8c78af6305dc5f344402be8acbd26304b2085"
},
"timestamp": 1586943701559,
"seed": "2e7537ac999c154f26c1f6db680a74d85c702773d0f244c30262bcf6ce2a7c02",
"hash": "5b193ff1cf8ac2f1aabe5fe7de85debb29e8f337bc89b135a590c1073800cf80",
"chains": {},
"address": "0x4592350babefcc849943db091b6c49f8b86f8aaa",
"signature": "0xa6bbc4cc1e50088492dc482801c4d4695d14f367b3b10e34f93a962e1a8213b634b7bfa6a95edc6bbc25a359cf9a4554d6dee72078a671f401b6aa667dcb1ab31c",
"data": {
"bytes": 7
}
}
}
chain1
has been deleted as a chain label but the record that was referred to by this chain label is still available and can be accessed using the chain2
label.
You can create a block containing a maximum of 1 record by running:
curl -XPOST "$api/blocks?pretty=true&max=1"
{
"took": 27,
"status": 201,
"data": {
"index": 1,
"root": "59cf7456a02ef842cb6b1d848ca0629b139da84877a3db0b981733a6619bc235",
"timestamp": 1586943702025,
"count": 1,
"previous": {
"root": "27d046333217d2be772104530c9414c2a52557a647c0e08d5de75df58babb3f7",
"proof": [
"e217a0734511aee3e1bc0371e179321fd629d252dfa64cc6425a61953965316f13224c",
"f871a014435818d91527af51393539ea61a76e5dc5356fd92796fa3686a8b1c685728e8080a0e7dd09b5787bfa9ab1602431023ae157c6d2805cb2bff5d7712442e4a099920780a0028fa281d9aa44d4f75b225b768d4e10a65654aac0fa02fabebc24557bb447098080808080808080808080",
"ea8820726576696f7573a027d046333217d2be772104530c9414c2a52557a647c0e08d5de75df58babb3f7"
]
}
}
}
The block creation API method returns the following informations:
took
is the number of milliseconds this request needed to be processed at server-side;status
is the HTTP status code;data
contains every piece of information related to the block you created;root
is the root hash of the block;index
is the block number, starting at 0;timestamp
is the record creation time (EPOCH millisecond);count
is the number of record contained in the block;previous
isnull
ifindex
is0
;root
is the root hash of the previous block;proof
is the associated proof in this block.
curl -XPOST "$api/blocks?pretty=true"
{
"took": 31,
"status": 201,
"data": {
"index": 2,
"root": "ad92e560fc5f015048ec2e4365fc32df7cc8ae8c799e02825347ef3be35563f9",
"timestamp": 1586943702084,
"count": 3,
"previous": {
"root": "59cf7456a02ef842cb6b1d848ca0629b139da84877a3db0b981733a6619bc235",
"proof": [
"f891a09c82087cd3fd12d04584140d142b4518761bba83d9ea3d3a8f0a8a5763230285808080a09d0d685972578ba90f341b8e062f1b4437734acc254039730b5fc83e20aefa628080a0401f6784185659d54fae44e2a82f91a4d0cfa20ebd184ad79826e06cd3f22930a05476c2d0eb9ba2ebff9382234af879a3d951149c5e4dfe3fb8bbc68213e0ae878080808080808080",
"f851a08513201653fd360f98eb7008d70b3268766f68676df2056b3358f0743cc2e0708080a0d07766d11ea9863d8bc904800141171b549f84e7d4bbfc9006b969b178cc09ab80808080808080808080808080",
"ea8820726576696f7573a059cf7456a02ef842cb6b1d848ca0629b139da84877a3db0b981733a6619bc235"
]
}
}
}
You can run a block creation again to see that by default no block is created if there is no pending record.
curl -XPOST "$api/blocks?pretty=true"
{
"took": 13,
"status": 200,
"data": null
}
If you want to allow the creation of an empty block, you can use the empty
option.
To be sure to create an empty block, you must use both empty=true
and max=0
.
curl -XPOST "$api/blocks?pretty=true&empty=true"
{
"took": 19,
"status": 201,
"data": {
"index": 3,
"root": "ad03acc1095cde8db7d49596e15de29299557e70d665e292269faf9cc7d0dc87",
"timestamp": 1586943702175,
"count": 0,
"previous": {
"root": "ad92e560fc5f015048ec2e4365fc32df7cc8ae8c799e02825347ef3be35563f9",
"proof": [
"e217a0a1656d0c8a2fc675dfa22648c17dd1627c4edb542ff883f3ac6a721c650e22c2",
"f851a089916489630c28154876ae3de149b1537a6b687003849ddafd466061faadb8628080a07a803ba3a2ba88adb0d7801b62a07d739bf8d426aa5454169fe8bd357963783680808080808080808080808080",
"ea8820726576696f7573a0ad92e560fc5f015048ec2e4365fc32df7cc8ae8c799e02825347ef3be35563f9"
]
}
}
}
To retrieve the pending block information you can run the following:
curl -XGET "$api/blocks?pretty=true"
{
"took": 6,
"status": 200,
"data": {
"count": 0,
"previous": {
"index": 3,
"root": "ad03acc1095cde8db7d49596e15de29299557e70d665e292269faf9cc7d0dc87",
"timestamp": 1586943702175,
"count": 0,
"previous": {
"root": "ad92e560fc5f015048ec2e4365fc32df7cc8ae8c799e02825347ef3be35563f9",
"proof": [
"e217a0a1656d0c8a2fc675dfa22648c17dd1627c4edb542ff883f3ac6a721c650e22c2",
"f851a089916489630c28154876ae3de149b1537a6b687003849ddafd466061faadb8628080a07a803ba3a2ba88adb0d7801b62a07d739bf8d426aa5454169fe8bd357963783680808080808080808080808080",
"ea8820726576696f7573a0ad92e560fc5f015048ec2e4365fc32df7cc8ae8c799e02825347ef3be35563f9"
]
}
}
}
}
You can retrieve a block by specifying its index in the path.
curl -XGET "$api/blocks/1?pretty=true"
{
"took": 2,
"status": 200,
"data": {
"index": 1,
"root": "59cf7456a02ef842cb6b1d848ca0629b139da84877a3db0b981733a6619bc235",
"timestamp": 1586943702025,
"count": 1,
"previous": {
"root": "27d046333217d2be772104530c9414c2a52557a647c0e08d5de75df58babb3f7",
"proof": [
"e217a0734511aee3e1bc0371e179321fd629d252dfa64cc6425a61953965316f13224c",
"f871a014435818d91527af51393539ea61a76e5dc5356fd92796fa3686a8b1c685728e8080a0e7dd09b5787bfa9ab1602431023ae157c6d2805cb2bff5d7712442e4a099920780a0028fa281d9aa44d4f75b225b768d4e10a65654aac0fa02fabebc24557bb447098080808080808080808080",
"ea8820726576696f7573a027d046333217d2be772104530c9414c2a52557a647c0e08d5de75df58babb3f7"
]
}
}
}
You can also retrieve it using its hash.
curl -XGET "$api/blocks/59cf7456a02ef842cb6b1d848ca0629b139da84877a3db0b981733a6619bc235?pretty=true"
{
"took": 2,
"status": 200,
"data": {
"index": 1,
"root": "59cf7456a02ef842cb6b1d848ca0629b139da84877a3db0b981733a6619bc235",
"timestamp": 1586943702025,
"count": 1,
"previous": {
"root": "27d046333217d2be772104530c9414c2a52557a647c0e08d5de75df58babb3f7",
"proof": [
"e217a0734511aee3e1bc0371e179321fd629d252dfa64cc6425a61953965316f13224c",
"f871a014435818d91527af51393539ea61a76e5dc5356fd92796fa3686a8b1c685728e8080a0e7dd09b5787bfa9ab1602431023ae157c6d2805cb2bff5d7712442e4a099920780a0028fa281d9aa44d4f75b225b768d4e10a65654aac0fa02fabebc24557bb447098080808080808080808080",
"ea8820726576696f7573a027d046333217d2be772104530c9414c2a52557a647c0e08d5de75df58babb3f7"
]
}
}
}
# create a record from a file
cat FILE | curl -XPOST -H "Content-Type: application/octet-stream" "$api/records" --data-binary @-
# redis interactive client
docker run --rm -it --network host redis redis-cli
# redis client command
docker run --rm -i --network host redis redis-cli info
docker run --rm -i --network host redis redis-cli eval "return #redis.call('keys', 'precedence.*')" 0
- ECMAScript 6 or Typescript with unit/integration tests, code coverage, code documentation, loggers with log level
- split modules into dedicated projects?
- NPM publication
- Redis auto-reconnection (bad gateway error)
precedence can be easily plugged to an open source project that provides a low latency data streaming platform for change data capture (CDC) named Debezium. We implemented a connector compliant with both Debezium and precedence and we have released it in the GitHub project inblocks/precedence-debezium. You should refer to this other project documentation to know more about the way precedence and Debezium can be plugged to each other.
If you want to run a demo by yourself you can check this page.