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:
tookis the number of millisecond this request needed to be processed at server-side;statusis the HTTP status code;datacontains every piece of information related to the original data you provided;provablecontains the information that you will be able to prove using precedence;idis the record identifier;seedis the obfuscated fingerprint of the rootseed;hashis the obfuscated fingerprint of the roothash;chainsis the rootchainsbut where keys and values are the obfuscated fingerprint of their original value;previousis the list of the record identifiers that are directly linked to this record;addressis the obfuscated fingerprint of rootaddress;signatureis the obfuscated fingerprint of rootsignature;
timestampis the record creation time (EPOCH millisecond);seedis the random data used for obfuscation;hashis the fingerprint of the original data;chainsis the map of relation between a chain and its last record identifier;addressis used for proof-of-ownership, corresponding to the public key of ECDSA key pair used to sign the roothash;signatureis the Ethereum signature of the roothash.
We can check that:
- the obfuscated fingerprint of
seedvalue is equal toprovable.seedvalue:
echo -n 'd86323c48bbc83e658420137d368cbcaa68ad3db060a8f52e6fa328d818675b1 d86323c48bbc83e658420137d368cbcaa68ad3db060a8f52e6fa328d818675b1' | sha256sum- the obfuscated fingerprint of the hash is equal to
provable.hashvalue:
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
chain1is equal to75e7db6f4670f1a2f71e4bbf758d3d2bc30ad8c3e52b82f5dc89e93199728b4d:
echo -n "f7a2f7002e8729ccceb374db92822431126f8583fb3358a08136eddf14e8db1c chain1" | sha256sum- the
chains.chain1value is equal to theprovable.chains.75e7db6f4670f1a2f71e4bbf758d3d2bc30ad8c3e52b82f5dc89e93199728b4dvalue: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:
tookis the number of milliseconds this request needed to be processed at server-side;statusis the HTTP status code;datacontains every piece of information related to the block you created;rootis the root hash of the block;indexis the block number, starting at 0;timestampis the record creation time (EPOCH millisecond);countis the number of record contained in the block;previousisnullifindexis0;rootis the root hash of the previous block;proofis 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.