├── .gitattributes ├── .gitignore ├── CHANGELOG.md ├── LICENSE.md ├── contexts └── webledger-v1.jsonld ├── diagrams ├── basic-ledger.svg ├── blocks.svg ├── ds-lifetime.svg ├── ecosystem.svg ├── ledger-events.svg └── system-state.svg ├── index.html ├── js ├── browser.js ├── constants.js └── index.js ├── package.json ├── respec-w3c-common.js ├── rollup.config.js ├── spec.css ├── utils.js ├── vocabulary.html └── webpack.config.js /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.sw[nop] 2 | *~ 3 | dist 4 | node_modules 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # web-ledger-context ChangeLog 2 | 3 | ## 5.0.0 - 2019-05-16 4 | 5 | ### Changed 6 | - **BREAKING**: Implement a new module structure. 7 | - Build and distribute static browser version with all contexts. 8 | - Export a `contexts` Map associating context URIs to contexts. 9 | - Export a `constants` Object associating short ids to contexts URIs. 10 | 11 | ## 4.0.0 - 2019-01-03 12 | 13 | ### Changed 14 | - Update capability terms. 15 | 16 | ## 3.0.0 - 2018-12-21 17 | 18 | ### Changed 19 | - Add `sequence`. 20 | 21 | ## 2.0.0 - 2018-12-18 22 | 23 | ### Changed 24 | - Add `targetNode`. 25 | 26 | ## 1.0.0 - 2018-12-06 27 | 28 | See git history for changes previous to this release. 29 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | All documents in this Repository are licensed by contributors under the [W3C Software and Document License](http://www.w3.org/Consortium/Legal/copyright-software). 2 | -------------------------------------------------------------------------------- /contexts/webledger-v1.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "@version": 1.1, 4 | "id": "@id", 5 | "type": "@type", 6 | 7 | "dc": "http://purl.org/dc/terms/", 8 | "jldp": "https://w3id.org/json-ld-patch#", 9 | "sec": "https://w3id.org/security#", 10 | "wl": "https://w3id.org/webledger#", 11 | "xsd": "http://www.w3.org/2001/XMLSchema#", 12 | 13 | "Config": "wl:Config", 14 | "Continuity2017": "wl:Continuity2017", 15 | "Continuity2017Elector": "wl:Continuity2017Elector", 16 | "Continuity2017GuarantorElector": "wl:Continuity2017GuarantorElector", 17 | "Continuity2017Peer": "wl:Continuity2017Peer", 18 | "ContinuityMergeEvent": "wl:ContinuityMergeEvent", 19 | "CreateWebLedgerRecord": "wl:CreateWebLedgerRecord", 20 | "UpdateWebLedgerRecord": "wl:UpdateWebLedgerRecord", 21 | "DeleteWebLedgerRecord": "wl:DeleteWebLedgerRecord", 22 | "Ed25519Signature2018": "sec:Ed25519Signature2018", 23 | "Ed25519VerificationKey2018": "sec:Ed25519VerificationKey2018", 24 | "Elector": "wl:Elector", 25 | "ElectorPool": "wl:ElectorPool", 26 | "EventTypeFilter": "wl:EventTypeFilter", 27 | "RecoveryElector": "wl:RecoveryElector", 28 | "RevocationCheck": "sec:RevocationCheck", 29 | "RsaSignature2018": "sec:RsaSignature2018", 30 | "RsaVerificationKey2018": "sec:RsaVerificationKey2018", 31 | "SignatureValidator2017": "wl:SignatureValidator2017", 32 | "SequentialList": "wl:SequentialList", 33 | "UnilateralConsensus2017": "wl:UnilateralConsensus2017", 34 | "WebLedgerConfiguration": "wl:WebLedgerConfiguration", 35 | "WebLedgerConfigurationEvent": "wl:WebLedgerConfigurationEvent", 36 | "WebLedgerEvent": "wl:WebLedgerEvent", 37 | "WebLedgerEventBlock": "wl:WebLedgerEventBlock", 38 | "WebLedgerOperationEvent": "wl:WebLedgerOperationEvent", 39 | "WebLedgerRecord": "wl:WebLedgerRecord", 40 | "ValidatorFilterByType": "wl:ValidatorFilterByType", 41 | 42 | "allowedAction": "sec:allowedAction", 43 | "approvedSigner": "wl:approvedSigner", 44 | "assertionMethod": {"@id": "sec:assertionMethod", "@type": "@id", "@container": "@set"}, 45 | "authentication": {"@id": "sec:authenticationMethod", "@type": "@id", "@container": "@set"}, 46 | "basisBlockHeight": "wl:basisBlockHeight", 47 | "blockHeight": "wl:blockHeight", 48 | "canonicalizationAlgorithm": "sec:canonicalizationAlgorithm", 49 | "capability": {"@id": "sec:capability", "@type": "@id"}, 50 | "capabilityAction": "sec:capabilityAction", 51 | "capabilityChain": {"@id": "sec:capabilityChain", "@type": "@id", "@container": "@list"}, 52 | "capabilityDelegation": {"@id": "sec:capabilityDelegationMethod", "@type": "@id", "@container": "@set"}, 53 | "capabilityInvocation": {"@id": "sec:capabilityInvocationMethod", "@type": "@id", "@container": "@set"}, 54 | "capabilityStatusList": {"@id": "sec:capabilityStatusList", "@type": "@id"}, 55 | "caveat": {"@id": "sec:caveat", "@type": "@id", "@container": "@set"}, 56 | "challenge": "sec:challenge", 57 | "consensusMethod": {"@id": "wl:consensusMethod", "@type": "@vocab"}, 58 | "consensusProofHash": {"@id": "wl:consensusProofHash", "@container": "@set"}, 59 | "controller": {"@id": "sec:controller", "@type": "@id"}, 60 | "created": {"@id": "dc:created", "@type": "xsd:dateTime"}, 61 | "creator": {"@id": "dc:creator", "@type": "@id"}, 62 | "defaultElector": {"@id": "wl:defaultElector", "@type": "@id", "@container": "@set"}, 63 | "delegator": {"@id": "sec:delegator", "@type": "@id"}, 64 | "digestAlgorithm": "sec:digestAlgorithm", 65 | "digestValue": "sec:digestValue", 66 | "domain": "sec:domain", 67 | "elector": {"@id": "wl:elector", "@type": "@id"}, 68 | "electorSelectionMethod": {"@id": "wl:electorSelectionMethod", "@type": "@id"}, 69 | "electorPool": {"@id": "wl:electorPool", "@type": "@id"}, 70 | "event": {"@id": "wl:event", "@type": "@id", "@container": ["@graph", "@set"]}, 71 | "eventHash": "wl:eventHash", 72 | "expirationDate": {"@id": "sec:expiration", "@type": "xsd:dateTime"}, 73 | "invocationTarget": {"@id": "sec:invocationTarget", "@type": "@id"}, 74 | "invoker": {"@id": "sec:invoker", "@type": "@id"}, 75 | "jws": "sec:jws", 76 | "ledger": {"@id": "wl:ledger", "@type": "@id"}, 77 | "ledgerConfiguration": {"@id": "wl:ledgerConfiguration", "@type": "@id", "@container": "@graph"}, 78 | "ledgerConfigurationValidator": {"@id": "wl:ledgerConfigurationValidator", "@type": "@id", "@container": "@set"}, 79 | "maximumElectorCount": {"@id": "wl:maximumElectorCount", "@type": "xsd:integer"}, 80 | "minimumProofsRequired": "sec:minimumProofsRequired", 81 | "minimumSignaturesRequired": "wl:minimumSignaturesRequired", 82 | "nonce": "sec:nonce", 83 | "operation": {"@id": "wl:operation", "@type": "@id", "@container": ["@graph", "@set"]}, 84 | "operationHash": {"@id": "wl:operationHash", "@container": "@set"}, 85 | "operationValidator": {"@id": "wl:operationValidator", "@type": "@id", "@container": "@set"}, 86 | "owner": {"@id": "sec:owner", "@type": "@id"}, 87 | "parentCapability": {"@id": "sec:parentCapability", "@type": "@id"}, 88 | "parentHash": {"@id": "wl:parentHash", "@container": "@set"}, 89 | "recordPatch": { 90 | "@id": "wl:recordPatch", 91 | "@type": "@id", 92 | "@container": "@graph", 93 | "@context": { 94 | "add": "jldp:add", 95 | "copy": "jldp:copy", 96 | "frame": {"@id": "jldp:from", "@type": "@id"}, 97 | "from": "jldp:from", 98 | "move": "jldp:move", 99 | "op": "jldp:op", 100 | "patch": {"@id": "jldp:patch", "@type": "@id", "@container": "@set"}, 101 | "path": "jldp:path", 102 | "remove": "jldp:remove", 103 | "replace": "jldp:replace", 104 | "target": {"@id": "jldp:target", "@type": "@id"}, 105 | "test": "jldp:test", 106 | "sequence": {"@id": "jldp:sequence", "@type": "xsd:integer"}, 107 | "value": "jldp:value" 108 | } 109 | }, 110 | "previousBlock": "wl:previousBlock", 111 | "previousBlockHash": "wl:previousBlockHash", 112 | "proof": {"@id": "sec:proof", "@type": "@id", "@container": "@graph"}, 113 | "proofAlgorithm": "sec:proofAlgorithm", 114 | "proofPurpose": {"@id": "sec:proofPurpose", "@type": "@vocab"}, 115 | "proofValue": "sec:proofValue", 116 | "publicKey": {"@id": "sec:publicKey", "@type": "@id", "@container": "@set"}, 117 | "publicKeyBase58": "sec:publicKeyBase58", 118 | "publicKeyPem": "sec:publicKeyPem", 119 | "record": {"@id": "wl:record", "@type": "@id", "@container": "@graph"}, 120 | "recommendedElector": {"@id": "wl:recommendedElector", "@container": "@set"}, 121 | "requiredProof": "sec:requiredProof", 122 | "revoked": {"@id": "sec:revoked", "@type": "xsd:dateTime"}, 123 | "sequence": {"@id": "jldp:sequence", "@type": "xsd:integer"}, 124 | "targetNode": {"@id": "wl:targetNode", "@type": "@id"}, 125 | "treeHash": "wl:treeHash", 126 | "validatorFilter": {"@id": "wl:validatorFilter", "@type": "@id"}, 127 | "validatorFilterByType": {"@id": "wl:validatorFilterType", "@type": "@vocab"}, 128 | "verificationMethod": {"@id": "sec:verificationMethod", "@type": "@id"}, 129 | "voter": {"@id": "wl:voter", "@type": "@id"} 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /diagrams/blocks.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /diagrams/ds-lifetime.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |107 | This document outlines a data model and syntax for expressing a 108 | set of ordered events in a decentralized system in way that can be 109 | cryptographically verified. This technology is useful when coordinating 110 | the recording of events, such as financial transactions, transfer of property, 111 | or time-stamped data that must be shared among coordinating parties. A 112 | primary goal of this ledger format is flexibility, allowing the 113 | pluggability of consensus algorithms, data structures for recording 114 | history, and the type of data that can be stored in the ledger. The format and 115 | protocol described in this document can be used by existing systems 116 | (e.g. Bitcoin, Ethereum, etc.) to expose their data and functionality in an 117 | interoperable fashion. 118 |
119 |There are a number of ways that one may participate in the development of 124 | this specification:
125 | 126 |145 | Decentralized systems often need to coordinate information on their 146 | operational state. While the entire state of the system doesn't need to be 147 | shared, the parts that affect the operation of the entire system are important. 148 | At their most basic, a decentralized system can be viewed as a 149 | state machine where events modify the state of the machine 150 | resulting in a new state: 151 |
152 | 153 |162 | There may be many different types of events in the system. Some events may 163 | handle system configuration, defining what the system is and isn't allowed 164 | to do. Some events may store data in the system that must be accessible by 165 | the entire system while other events snapshot the state of the system 166 | for performance and auditing purposes. Other events record the consensus of 167 | the system as a whole at a given point in time so that participants in the 168 | system can know that other participants agree with their view of the system. 169 |
170 | 171 |180 | Each event may affect the global system state in some way. This means that 181 | the current state is a representation of all the states and events that came 182 | before it. 183 |
184 | 185 |193 | It is typically important to optimize the storage of the events and 194 | package these events into a data structure called a block. These 195 | blocks are then "chained" together into a system that is often 196 | referred to as a blockchain. 197 |
198 |207 | In certain decentralized systems, like financial or healthcare systems, 208 | auditing these states and events is important to ensure that they are 209 | operating in an acceptable way from a regulatory perspective. 210 | Thus a verifiable record of these events and states is an important component 211 | of the system design, but has not been a practical endeavor until recently. 212 |
213 |214 | Due to recent advances in cryptography and decentralized systems design a new 215 | set of technologies called cryptographic ledgers 216 | (aka blockchains) have enabled the 217 | recording of state and events in a ledger where the ledger can be distributed 218 | and independently verified using cryptography. Some of these ledger systems are 219 | trustless, meaning that no trust (other than a trust in mathematics) is 220 | necessary in order to participate in the system. Other ledger systems are 221 | permissioned, meaning that some trust in third parties is required to 222 | ensure the accuracy of the ledger. 223 |
224 | 225 |
234 | These cryptographic ledgers operate in an ecosystem consisting of the
235 | following actors. A ledger node modifies an instance of a
236 | cryptographic ledger based on the current configuration of the ledger.
237 | The ledger node tracks a set of pending ledger events that are
238 | candidates for being written to the ledger and writes them to the ledger
239 | when it believes consensus has been reached. A ledger agent may be
240 | used by any system that communicates over HTTP to instruct a
241 | ledger node to perform a specified action on the ledger.
242 |
243 |
245 |
253 | This specification details an extensible data model and syntax for expressing 254 | cryptographic ledgers and a protocol for reading and writing to ledgers. 255 | The data model in this specification is designed to be protocol-agnostic 256 | and flexible, supporting pluggability of consensus algorithms, various data 257 | structures for recording history, and enabling a wide range of data types 258 | to be stored in the ledger. 259 |
260 | 261 |265 | This document is a detailed specification for ... 266 |
267 | 268 |279 | This document is organized as follows: 280 |
281 | 282 |387 | To provide the greatest amount of flexibility, the data model is a graph. 388 | If a formalized data model is desired, RDF may be utilized but is not necessary. 389 |
390 | 391 |392 | To ensure that the syntax will be easily adopted by developers, and supports 393 | a graph-based data model, it is RECOMMENDED that the implementation syntax is 394 | JSON-LD (or similarly compatible syntax). Other RDF-compatible syntaxes MAY 395 | also be used to express the ledger semantics. This ensures that the syntax is 396 | processable by widely adopted JSON tooling while also ensuring that the 397 | data model is robust enough to handle decentralized extensibility without 398 | name clashes or conflicts. 399 |
400 | 401 |402 | A ledger consists of a series of entries. This section outlines the basic 403 | types of entries that all Web Ledgers support. A particular Web Ledger MAY 404 | contain more than these basic entries. 405 |
406 | 407 |411 | A block contains one or more changes to the state machine. 412 | Blocks are typically used as a storage optimization to bundle a set of 413 | changes to the state machine. There can be many types of blocks. 414 | This specification details the basic set of blocks that all Web Ledgers 415 | may express. 416 |
417 | 418 |424 | A configuration block specifies which software algorithms should be applied 425 | when processing a particular Web Ledger. The first entry in a Ledger is 426 | typically an entry called a genesis block. The genesis block has the 427 | following basic layout: 428 |
429 | 430 |431 | { 432 | "@context": "https://w3id.org/web-ledger/v1", 433 | "id": BLOCK_ID, 434 | "type": "LedgerConfigurationBlock", 435 | "ledgerConfig": { 436 | "id": LEDGER_ID, 437 | "type": "LedgerConfiguration", 438 | "name": "example", 439 | "description": "This is an example ledger.", 440 | "storageMechanism": STORAGE_DATA_STRUCTURE, 441 | "consensusAlgorithm": CONSENSUS_ALGORITHM, 442 | "previousBlock": { 443 | "hash": "urn:sha256:0000000000000000000000000000000000000000000000000000000000000000" 444 | }, 445 | "signature": SIGNATURE_VALUE 446 | } 447 |448 | 449 |
450 | In the example above, LEDGER_ID
is used to uniquely identify the
451 | ledger (e.g. did:f6ea280f-8011-4502-a29f-464954de3427
).
452 | BLOCK_ID
is used to uniquely identify the block in the ledger
453 | (e.g. did:f6ea280f-8011-4502-a29f-464954de3427/blocks/1
.
454 | STORAGE_DATA_STRUCTURE
is used to identify the storage mechanism
455 | that is used in the ledger (e.g. SequentialList
) so that
456 | serializing and
457 | deserializing the contents of the ledger remains consistent across ledgers.
458 | SIGNATURE_VALUE
is used to perform the cryptographic proof that
459 | the ledger block was created by the entity identified in the signature. A more
460 | complete example of a genesis block is
461 | available in the appendix.
462 |
465 | A standard configuration block update only differs from a genesis block in
466 | that the previousBlock
value refers to the block before the
467 | current block:
468 |
471 | { 472 | "@context": "https://w3id.org/web-ledger/v1", 473 | "id": BLOCK_ID, 474 | "type": "LedgerConfigurationBlock", 475 | "ledgerConfig": { 476 | "id": LEDGER_ID, 477 | "type": "LedgerConfiguration", 478 | "name": "example", 479 | "description": "This is an example ledger.", 480 | "storageMechanism": STORAGE_DATA_STRUCTURE, 481 | "consensusAlgorithm": CONSENSUS_ALGORITHM, 482 | "previousBlock": { 483 | "id": PREVIOUS_BLOCK_ID, 484 | "hash": PREVIOUS_BLOCK_HASH 485 | }, 486 | "signature": SIGNATURE_VALUE 487 | } 488 |489 | 490 |
491 | The PREVIOUS_BLOCK_ID
is the identifier of the previous
492 | block in the ledger (e.g.
493 | did:f6ea280f-8011-4502-a29f-464954de3427/blocks/1
) and the
494 | PREVIOUS_BLOCK_HASH
value (e.g.
495 | urn:sha256:abd465d34f7a3f0f7d849550eb9fc32c17d12881da6b524da0a96e12cc984538
496 | is a hash of the previous block in the ledger.
497 |
505 | A storage block stores data in a ledger and has the following general layout: 506 |
507 | 508 |509 | { 510 | "@context": ["https://w3id.org/web-ledger/v1", MARKET_VERTICAL_CONTEXT], 511 | "id": BLOCK_ID, 512 | "type": "LedgerStorageBlock", 513 | "setObject": [ OBJECTS ], 514 | "previousBlock": { 515 | "id": PREVIOUS_BLOCK_ID 516 | "hash": PREVIOUS_BLOCK_HASH 517 | }, 518 | "signature": SIGNATURE_VALUE 519 | } 520 |521 | 522 |
523 | When storing data in the ledger, one may use a
524 | MARKET_VERTICAL_CONTEXT
to add semantics to the objects stored in
525 | OBJECTS
526 | (e.g. https://w3id.org/vaccinations/v1
).
527 | OBJECTS
are one or more JSON objects that can be stored in
528 | the ledger. It is expected that each object has a unique identifier to
529 | enable searching based on that identifier. A detailed
530 | example of a storage event is included in
531 | the appendix.
532 |
540 | It's currently not specified in a configuration event how often consensus 541 | events should occur. The options are: per event, or every N events. This is 542 | an active area of research and debate. 543 |
544 | 545 |546 | A consensus event is an assertion that there is agreement on a subset of entries 547 | in a ledger. Some ledgers do not require consensus events as each event 548 | establishes an acceptable level of consensus. Other ledgers require consensus 549 | events after a pre-determined amount of time. An example of the basic layout 550 | of a consensus event is shown below: 551 |
552 | 553 |554 | { 555 | "@context": "https://w3id.org/web-ledger/v1", 556 | "id": BLOCK_ID, 557 | "type": "ConsensusBlock", 558 | "previousBlock": { 559 | "id": PREVIOUS_BLOCK_ID 560 | "hash": PREVIOUS_BLOCK_HASH 561 | }, 562 | "signature": [ SIGNATURES ] 563 | } 564 |565 | 566 |
567 | A consensus event has a relatively simple definition. It consists of a
568 | number of SIGNATURES
from notaries as determined by the previous
569 | configuration event. A more complete
570 | example of a consensus event
571 | is located in the appendix.
572 |
580 | A checkpoint event may be used to quickly bootstrap new mirrors for a ledger. 581 | An example of the basic layout of a checkpoint event is shown below: 582 |
583 | 584 |585 | { 586 | "@context": "https://w3id.org/web-ledger/v1", 587 | "id": BLOCK_ID, 588 | "type": "LedgerCheckpointBlock", 589 | "checkpointLog": CHECKPOINT_LOG_URL, 590 | "checkpointLogHash": CHECKPOINT_LOG_HASH, 591 | "signature": [ SIGNATURES ] 592 | } 593 |594 | 595 |
596 | A checkpoint event declares a CHECKPOINT_LOG_URL
597 | (e.g. https://example.org/ledger-agents/example/checkpoints/132
) and a
598 | CHECKPOINT_LOG_HASH
599 | (e.g. urn:sha256:7fa3b9eaa8d92d2b87abf83d88a92ff23
).
600 | All notaries typically download the checkpoint log and
601 | check it before providing signatures noting that the checkpoint log is valid.
602 | There is a detailed
603 | example of a checkpoint event
604 | in the appendix.
605 |
608 | How checkpoints are generated are a current topic of debate. The configuration 609 | event doesn't specify how often checkpoints can/should happen. It is also 610 | debatable that a checkpoint should be included in a consensus event and 611 | shouldn't be a separate event. 612 |
613 | 614 |622 | The previous section defined the data model and messages that can be used 623 | to create and operate a ledger. This section provides the Ledger Agent 624 | HTTP API endpoints that may be used in conjunction with the messages in the 625 | previous section to create and operate a ledger. 626 |
627 | 628 |629 | Note that the API proposed here only has one implementation and, while designed 630 | to be flexible, does not have enough deployment experience to be used in 631 | production systems that require strong interoperability guarantees. This is 632 | a work in progress. 633 |
634 | 635 |636 | The `ledgerAgentStatusService` may not be necessary. Instead some text 637 | could be added indicating that the `id` of the Ledger Agent can be 638 | retrieved to get its status information. 639 |
640 | 641 |Service | 644 |Example URL | 645 |Description | 646 | 647 | 648 |
---|---|---|
ledgerAgentCreateService | 650 |POST /ledger-agents | 651 |Create a ledger agent. | 652 |
ledgerAgentListService | 655 |GET /ledger-agents | 656 |Get all ledger agents. | 657 |
ledgerAgentStatusService | 660 |GET /ledger-agents/{agent} | 661 |Get the current status of the ledger agent. | 662 |
ledgerEventService | 665 |POST /ledger-agents/{agent}/events | 666 |Request the addition of an event to ledger. | 667 |
ledgerBlockService | 670 |GET /ledger-agents/{agent}/blocks | 671 |Get a specific block from the ledger. | 672 |
ledgerQueryService | 675 |GET /ledger-agents/{agent}/query | 676 |Query the current state of the ledger. | 677 |
685 | A website may provide service endpoint discover by embedding JSON-LD in their
686 | top-most HTML web page (e.g. at https://example.com/
):
687 |
690 | <!DOCTYPE html> 691 | <html lang="en"> 692 | <head> 693 | <meta charset="utf-8"> 694 | <title>Example Website</title> 695 | <link rel="stylesheet" href="style.css"> 696 | <script src="script.js"></script> 697 | <script type="application/ld+json"> 698 | { 699 | "@context": "https://w3id.org/discovery/v1", 700 | "id": "https://example.com/", 701 | "name": "Example Website", 702 | "ledgerAgentCreateService": "https://example.com/ledger-agents", 703 | "ledgerAgentListService": "https://example.com/ledger-agents" 704 | } 705 | </script> 706 | </head> 707 | <body> 708 | <!-- page content --> 709 | </body> 710 | </html> 711 |712 | 713 |
714 | Service descriptions may also be requested via content negotiation.
715 | In the following example a JSON-compatible service description is provided
716 | (e.g. curl -H "Accept: application/json" https://example.com/
):
717 |
720 | { 721 | "@context": "https://w3id.org/discovery/v1", 722 | "id": "https://example.com/", 723 | "name": "Example Website", 724 | "ledgerAgentCreateService": "https://example.com/ledger-agents", 725 | "ledgerAgentListService": "https://example.com/ledger-agents" 726 | } 727 |728 | 729 |
735 | A ledger is created by performing an HTTP POST of a
736 | LedgerConfigurationBlock
737 | to the ledgerAgentCreateService
. The following HTTP status codes
738 | are defined for this service:
739 |
HTTP Status | 744 |Description | 745 | 746 | 747 |
---|---|
201 | 749 |
750 | Ledger creation was successful. The HTTP Location header will
751 | contain the URL for the newly created ledger.
752 | |
753 |
400 | 756 |Ledger creation failed. | 757 |
409 | 760 |A duplicate ledger exists. | 761 |
766 | An example exchange of a ledger creation is shown below: 767 |
768 | 769 |770 | POST /ledger-agents HTTP/1.1 771 | Host: example.com 772 | Content-Type: application/ld+json 773 | Content-Length: 1062 774 | Accept: application/ld+json, application/json, text/plain, */* 775 | Accept-Encoding: gzip, deflate 776 | 777 | { 778 | "@context": "https://w3id.org/web-ledger/v1", 779 | "id": "did:1628bf39-c8f9-453f-93d7-0fbdebb3dfef/blocks/1", 780 | "type": "LedgerConfigurationBlock", 781 | "ledgerConfig": { 782 | "id": "did:1628bf39-c8f9-453f-93d7-0fbdebb3dfef", 783 | "type": "LedgerConfiguration", 784 | "name": "example", 785 | "description": "An example ledger.", 786 | "storageMechanism": "SequentialList", 787 | "consensusAlgorithm": { 788 | "type": "ProofOfSignature2016", 789 | "approvedSigner": [ 790 | "http://blue.example.com/keys/234", 791 | "http://red.example.com/keys/987", 792 | ], 793 | "minimumSignaturesRequired":1 794 | } 795 | }, 796 | "previousBlock": { 797 | "hash": "urn:sha256:0000000000000000000000000000000000000000000000000000000000000000" 798 | }, 799 | "signature": { 800 | "type": "RsaSignature2016", 801 | "created": "2016-10-14T18:35:33Z", 802 | "creator": "http://blue.example.com/keys/234", 803 | "signatureValue": "HvfvRQ57EO...J0Q==" 804 | } 805 | } 806 |807 | 808 |
809 | If the creation of the ledger was successful, an HTTP 201 status code is 810 | expected in return: 811 |
812 | 813 |814 | HTTP/1.1 201 Created 815 | Location: http://ledger.example.com/ledger-agents/example 816 | Cache-Control: no-cache, no-store, must-revalidate 817 | Pragma: no-cache 818 | Expires: 0 819 | Date: Fri, 14 Oct 2016 18:35:33 GMT 820 | Connection: keep-alive 821 | Transfer-Encoding: chunked 822 |823 | 824 |
830 | One can get a list of active ledgers on a server by performing an HTTP GET on
831 | the ledgerListService
. The following HTTP status codes
832 | are defined for this service:
833 |
HTTP Status | 838 |Description | 839 | 840 | 841 |
---|---|
200 | 843 |844 | The list of ledgers was found and will be returned in the body of the response. 845 | | 846 |
404 | 849 |850 | The list of ledgers was not found at the given URL. 851 | | 852 |
857 | An example exchange of getting a list of ledgers on an HTTP server is shown 858 | below: 859 |
860 | 861 |862 | GET /ledger-agents HTTP/1.1 863 | Host: example.com 864 | Connection: keep-alive 865 | Accept: application/ld+json, application/json, text/plain, */* 866 | Accept-Encoding: gzip, deflate, sdch 867 | Accept-Language: en-US,en;q=0.8 868 |869 | 870 |
871 | If retrieving the list of ledgers is successful, a HTTP 200 response is 872 | expected: 873 |
874 | 875 |876 | HTTP/1.1 200 OK 877 | Cache-Control: no-cache, no-store, must-revalidate 878 | Pragma: no-cache 879 | Expires: 0 880 | Access-Control-Allow-Origin: * 881 | Vary: Accept, Accept-Encoding 882 | Content-Type: application/ld+json; charset=utf-8 883 | Etag: W/"91d-mHiDWL0kix4rxP7JCtfVCA" 884 | Content-Encoding: gzip 885 | Date: Fri, 14 Oct 2016 18:46:04 GMT 886 | Connection: keep-alive 887 | Transfer-Encoding: chunked 888 | 889 | { 890 | "ledgerAgent": [ 891 | { 892 | "id": "https://example.com/ledger-agents/example", 893 | "name": "example", 894 | "ledgerAgentStatusService": "https://example.com/ledger-agents/example", 895 | "ledgerQueryService": "https://example.com/ledger-agents/example/query", 896 | "ledgerEventService": "https://example.com/ledger-agents/example/events", 897 | "ledgerBlockService": "https://example.com/ledger-agents/example/blocks", 898 | "ledgerConfig": { 899 | "id": "did:de7adbe7-79f2-425a-9dfb-76a234782f30", 900 | "type": "LedgerConfiguration", 901 | "name": "example", 902 | "description": "An example ledger.", 903 | "storageMechanism": "SequentialList", 904 | "consensusAlgorithm": { 905 | "type": "ProofOfSignature2016", 906 | "approvedSigner": [ 907 | "https://blue.example.com/keys/234", 908 | "https://red.example.com/keys/789" 909 | ], 910 | "minimumSignaturesRequired": 1 911 | } 912 | }, 913 | "latestBlock": { 914 | "id": "did:de7adbe7-79f2-425a-9dfb-76a234782f30/blocks/1", 915 | "hash": "urn:sha256:7eb0603c9a3982284c7db09b1eb40bc85a1177bdc594b027fba0e746b79db15b" 916 | }, 917 | "nextBlock": { 918 | "id": "did:de7adbe7-79f2-425a-9dfb-76a234782f30/blocks/2" 919 | } 920 | }, 921 | { 922 | ... NEXT_LEDGER_IN_LIST ... 923 | } 924 | ] 925 | } 926 |927 | 928 |
934 | The metadata related to a ledger agent may be fetched by performing an HTTP GET
935 | on the ledgerAgentStatusService
. The following HTTP status codes
936 | are defined for this service:
937 |
HTTP Status | 942 |Description | 943 | 944 | 945 |
---|---|
200 | 947 |948 | The ledger agent status was found and will be returned in the body of the response. 949 | | 950 |
404 | 953 |954 | The ledger agent status was not found at the given URL. 955 | | 956 |
961 | An example exchange of fetching metadata for a ledger is shown below: 962 |
963 | 964 | 965 |966 | GET /ledger-agents/example HTTP/1.1 967 | Host: example.com 968 | Connection: keep-alive 969 | Accept: application/ld+json, application/json, text/plain, */* 970 | Accept-Encoding: gzip, deflate, sdch 971 | Accept-Language: en-US,en;q=0.8 972 |973 | 974 |
975 | If retrieving the ledger metadata is successful, an HTTP 200 response is 976 | expected: 977 |
978 | 979 |980 | HTTP/1.1 200 OK 981 | Cache-Control: no-cache, no-store, must-revalidate 982 | Pragma: no-cache 983 | Expires: 0 984 | Access-Control-Allow-Origin: * 985 | Vary: Accept, Accept-Encoding 986 | Content-Type: application/ld+json; charset=utf-8 987 | Etag: W/"91d-mHiDWL0kix4rxP7JCtfVCA" 988 | Content-Encoding: gzip 989 | Date: Fri, 14 Oct 2016 18:46:04 GMT 990 | Connection: keep-alive 991 | Transfer-Encoding: chunked 992 | 993 | { 994 | "id": "https://example.com/ledger-agents/example", 995 | "name": "example", 996 | "ledgerAgentStatusService": "https://example.com/ledger-agents/example", 997 | "ledgerQueryService": "https://example.com/ledger-agents/example/query", 998 | "ledgerEventService": "https://example.com/ledger-agents/example/events", 999 | "ledgerBlockService": "https://example.com/ledger-agents/example/blocks", 1000 | "ledgerConfig": { 1001 | "id": "did:de7adbe7-79f2-425a-9dfb-76a234782f30", 1002 | "type": "LedgerConfiguration", 1003 | "name": "example", 1004 | "description": "An example ledger.", 1005 | "storageMechanism": "SequentialList", 1006 | "consensusAlgorithm": { 1007 | "type": "ProofOfSignature2016", 1008 | "approvedSigner": [ 1009 | "https://blue.example.com/keys/234", 1010 | "https://red.example.com/keys/789" 1011 | ], 1012 | "minimumSignaturesRequired":1 1013 | } 1014 | }, 1015 | "latestBlock": { 1016 | "id": "did:de7adbe7-79f2-425a-9dfb-76a234782f30/blocks/1", 1017 | "hash": "urn:sha256:7eb0603c9a3982284c7db09b1eb40bc85a1177bdc594b027fba0e746b79db15b" 1018 | }, 1019 | "nextBlock": { 1020 | "id": "did:de7adbe7-79f2-425a-9dfb-76a234782f30/blocks/2" 1021 | } 1022 | } 1023 |1024 | 1025 |
1031 | Appending to a ledger can be achieved by performing an HTTP POST of a
1032 | LedgerStorageBlock
1033 | to the ledgerAppendService
. The following HTTP status codes
1034 | are defined for this service:
1035 |
HTTP Status | 1040 |Description | 1041 | 1042 | 1043 |
---|---|
201 | 1045 |1046 | The ledger block was sucessfully appended. 1047 | | 1048 |
400 | 1051 |1052 | The ledger block failed to be appended. 1053 | | 1054 |
409 | 1057 |1058 | The ledger block with the given identifier already exists. 1059 | | 1060 |
1065 | An example of an event being appended to a ledger is shown below: 1066 |
1067 | 1068 |1069 | POST /ledger-agents/example/events HTTP/1.1 1070 | Host: example.com 1071 | Connection: keep-alive 1072 | Content-Length: 1054 1073 | Content-Type: application/json;charset=UTF-8 1074 | Accept: application/ld+json, application/json, text/plain, */* 1075 | Accept-Encoding: gzip, deflate 1076 | Accept-Language: en-US,en;q=0.8 1077 | 1078 | { 1079 | "@context": ["https://w3id.org/web-ledger/v1", "https://w3id.org/fema/v1"], 1080 | "type": "LedgerStorageEvent", 1081 | "setObject": [{ 1082 | "id": "https://fema.gov/credentials/9754457", 1083 | "type": ["Credential", "EmergencyResponderCredential"], 1084 | "claim": { 1085 | "id": "did:bc380e48-a6d9-4602-ab20-1beb403d4bcc", 1086 | "emsLicense": { 1087 | "id": "ems:FF-12-01655", 1088 | "status": "valid" 1089 | } 1090 | } 1091 | }], 1092 | "signature": { 1093 | "type": "RsaSignature2016", 1094 | "created": "2016-10-14T19:47:15Z", 1095 | "creator": "https://example.com/keys/fema-key-1", 1096 | "signatureValue": "JoS27wqaTX...s0mpBFMgXIMw==" 1097 | } 1098 | } 1099 |1100 | 1101 |
1102 | If the storage attempt is successful, a HTTP 200 response is expected: 1103 |
1104 | 1105 |1106 | HTTP/1.1 201 Created 1107 | Location: https://example.com/ledger-agents/example/events?id=d1328828-3d44-4e14-9c3a-263af54ed032 1108 | Cache-Control: no-cache, no-store, must-revalidate 1109 | Pragma: no-cache 1110 | Expires: 0 1111 | Date: Fri, 14 Oct 2016 19:47:16 GMT 1112 | Connection: keep-alive 1113 | Transfer-Encoding: chunked 1114 |1115 | 1116 |
1122 | A ledger read for an block is achieved by performing an HTTP GET on
1123 | a ledger block identifier. The list of ledger blocks is available by performing
1124 | an HTTP GET on the ledgerBlockService
. The following HTTP status
1125 | codes are defined for this service:
1126 |
HTTP Status | 1131 |Description | 1132 | 1133 | 1134 |
---|---|
200 | 1136 |1137 | Retrieval of the ledger block was successful. 1138 | | 1139 |
404 | 1142 |1143 | The ledger block was not found at the given URL. 1144 | | 1145 |
1150 | An example retrieval of a ledger block is shown below: 1151 |
1152 | 1153 |1154 | GET /ledger-agents/example/blocks?id=did:de7adbe7-79f2-425a-9dfb-76a234782f30/blocks/2 HTTP/1.1 1155 | Host: example.com 1156 | Connection: keep-alive 1157 | Accept: application/ld+json, application/json, text/plain, */* 1158 | Accept-Encoding: gzip, deflate, sdch 1159 | Accept-Language: en-US,en;q=0.8 1160 |1161 | 1162 |
1163 | If the ledger block retrieval is successful, a HTTP 200 response is expected: 1164 |
1165 | 1166 |1167 | HTTP/1.1 200 OK 1168 | Cache-Control: no-cache, no-store, must-revalidate 1169 | Pragma: no-cache 1170 | Expires: 0 1171 | Access-Control-Allow-Origin: * 1172 | Vary: Accept, Accept-Encoding 1173 | Content-Type: application/ld+json; charset=utf-8 1174 | Etag: W/"41e-PJKXv/OxofX29WykKb3PZg" 1175 | Content-Encoding: gzip 1176 | Date: Fri, 14 Oct 2016 20:20:44 GMT 1177 | Connection: keep-alive 1178 | Transfer-Encoding: chunked 1179 | 1180 | { 1181 | "@context": ["https://w3id.org/web-ledger/v1", "https://w3id.org/fema/v1"], 1182 | "id": "did:de7adbe7-79f2-425a-9dfb-76a234782f30/blocks/2", 1183 | "type": "LedgerStorageBlock", 1184 | "setObject": [{ 1185 | "id": "https://fema.gov/credentials/9754457", 1186 | "type": ["Credential", "EmergencyResponderCredential"], 1187 | "claim": { 1188 | "id": "did:bc380e48-a6d9-4602-ab20-1beb403d4bcc", 1189 | "emsLicense": { 1190 | "id": "ems:FF-12-01655", 1191 | "status": "valid" 1192 | } 1193 | } 1194 | }], 1195 | "previousBlock": { 1196 | "id": "did:de7adbe7-79f2-425a-9dfb-76a234782f30/blocks/1", 1197 | "hash": "urn:sha256:7eb0603c9a3982284c7db09b1eb40bc85a1177bdc594b027fba0e746b79db15b" 1198 | }, 1199 | "signature": { 1200 | "type": "RsaSignature2016", 1201 | "created": "2016-10-14T19:47:15Z", 1202 | "creator": "http://example.com/keys/789", 1203 | "signatureValue": "JoS27wqa...BFMgXIMw==" 1204 | } 1205 | } 1206 |1207 | 1208 |
1215 | The current state machine of a ledger may be queried by performing an
1216 | HTTP GET on the ledgerQueryService
. The following HTTP status
1217 | codes are defined for this service:
1218 |
HTTP Status | 1223 |Description | 1224 | 1225 | 1226 |
---|---|
200 | 1228 |1229 | Retrieval of the latest state machine object was successful. 1230 | | 1231 |
400 | 1234 |1235 | The query was malformed. 1236 | | 1237 |
404 | 1240 |1241 | The given state machine object was not found. 1242 | | 1243 |
1248 | An example query of a state machine in a ledger is shown below: 1249 |
1250 | 1251 |1252 | GET /ledger-agents/example/query?id=http://www.coupon-clearing.org/coupons/486211708 HTTP/1.1 1253 | Host: example.com 1254 | Connection: keep-alive 1255 | Accept: application/ld+json, application/json, text/plain, */* 1256 | Accept-Encoding: gzip, deflate, sdch 1257 | Accept-Language: en-US,en;q=0.8 1258 |1259 | 1260 |
1261 | If the query is successful, a HTTP 200 response is expected: 1262 |
1263 | 1264 |1265 | { 1266 | "id": "http://www.coupon-clearing.org/coupons/486211708", 1267 | "type": ["Credential", "DiscountCoupon"], 1268 | "claim": { 1269 | "id": "upc:956578900933", 1270 | "discount": "$3", 1271 | "description": "Discount when you buy 5 pounds of JuicyGreen Apples", 1272 | "status": "redeemed" 1273 | } 1274 | } 1275 |1276 | 1277 |
1288 | { 1289 | "@context": "https://w3id.org/web-ledger/v1", 1290 | "id": "did:f6ea280f-8011-4502-a29f-464954de3427/blocks/1", 1291 | "type": "LedgerConfigurationBlock", 1292 | "ledgerConfig": { 1293 | "id": "did:f6ea280f-8011-4502-a29f-464954de3427", 1294 | "type": "LedgerConfiguration", 1295 | "name": "example", 1296 | "description": "example ledger", 1297 | "storageMechanism": "SequentialList", 1298 | "consensusAlgorithm": { 1299 | "type": "ProofOfSignature2016", 1300 | "approvedSigner": [ 1301 | "https://blue.example.com/keys/j37f8", 1302 | "https://red.example.com/keys/83hfk", 1303 | ], 1304 | "minimumSignaturesRequired":1 1305 | } 1306 | }, 1307 | "previousBlock": { 1308 | "hash": "urn:sha256:0000000000000000000000000000000000000000000000000000000000000000" 1309 | }, 1310 | "signature": { 1311 | "type": "RsaSignature2016", 1312 | "created": "2016-10-05T11:47:26Z", 1313 | "creator": "http://blue.example.com/keys/j37f8", 1314 | "signatureValue": "RG+t2EbnMKr4zIwgncLHTb/JvAZ/EIXmTXrrad7DBdlchKPPC9j91N793eHY5UYx4zx7PTDnU2HlW9zqQD1EMBwI7TtqE7BfvxOFodjKJ/Aw16vpAmw2h2Jo9NBu4BvFWsLPCiMLHuW7Vxo7XDkGVfaZUqk/X2q/xpRmqJ1tOlNgivUH8bIm/TUAG3g90DMN9s5zImVyB4B20zMJk8K50BbpHYKUVNWCaHnv9F4VvUUa+AdNeNlC8W1F5j2WChyXzd+51bervxQErZUDFyocW/xEYPvJXPSGnL0ARBDggKQDe1M3bg8w7GnMGrJBieNZAuK2mxOtF2rOPDU3oMk3ZQ==" 1315 | } 1316 | } 1317 |1318 | 1319 |
1320 | { 1321 | "@context": "https://w3id.org/web-ledger/v1", 1322 | "id": "https://example.us.gov/ledger-agents/emergency-response/1", 1323 | "type": "LedgerConfigurationBlock", 1324 | "storageMechanism": "SequentialList", 1325 | "consensusAlgorithm": { 1326 | "type": "ProofOfSignature2016", 1327 | "approvedSigner": [ 1328 | "https://fema.example.us.gov/i/ofp", 1329 | "https://tsa.example.us.gov/i/vclaims", 1330 | "https://dhs.example.us.gov/i/credentialing", 1331 | ], 1332 | "minimumSignaturesRequired": 1 1333 | }, 1334 | "nextBlock": "https://example.us.gov/ledger-agents/emergency-response/2", 1335 | "signature": { 1336 | "type": "LinkedDataSignature2016", 1337 | "created": "2016-09-19T17:19:52Z", 1338 | "creator": "https://fema.example.gov/i/credentialing/keys/7f6", 1339 | "signatureValue": "pjeyuFq9idhwHGfGFzv...9fjsk==" 1340 | } 1341 | } 1342 |1343 | 1344 |
1345 | { 1346 | "@context": [ 1347 | "https://w3id.org/web-ledger/v1", 1348 | "https://w3id.org/cryptocurrencies/v1" 1349 | ], 1350 | "id": "bytecoin:block:23fa73bb201c738d", 1351 | "type": "LedgerConfigurationBlock", 1352 | "storageMechanism": "MerkleTree", 1353 | "consensusAlgorithm": { 1354 | "type": "ProofOfWork2016", 1355 | "proofOfWorkAlgorithm": "Bitcoin", 1356 | "targetDifficulty": "199312067531.243" 1357 | }, 1358 | "signature": { 1359 | "type": "LinkedDataSignature2016", 1360 | "created": "2017-01-24T02:10:21Z", 1361 | "creator": "bytecoin:keys:23f3b2c8183bdd52aff689", 1362 | "signatureValue": "90D4cFqT/yKPiwd/GFzv...NJGL==" 1363 | } 1364 | } 1365 |1366 | 1367 |
1368 | { 1369 | "@context": [ 1370 | "https://w3id.org/web-ledger/v1", 1371 | "https://w3id.org/cryptocurrencies/v1" 1372 | ], 1373 | "id": "https://example-consortium.com/private-ledgers/loans/real-estate/1", 1374 | "type": "LedgerConfigurationBlock", 1375 | "storageMechanism": "SequentialList", 1376 | "consensusAlgorithm": { 1377 | "type": "ProofOfBallot2015", 1378 | "minimumQuorumPercentage": "0.51", 1379 | "minimumVotePercentage": "0.67", 1380 | "approvedSigner": [ 1381 | "https://regulator-a.gov/i/bank-oversight", 1382 | "https://regulator-b.gov/i/consumer-protection", 1383 | "https://bank-x.com/i/housing", 1384 | "https://bank-y.com/i/corporate-loans", 1385 | "https://bank-z.com/i/swaps", 1386 | ] 1387 | }, 1388 | "signature": [{ 1389 | "type": "LinkedDataSignature2016", 1390 | "created": "2018-04-16T19:34:18Z", 1391 | "creator": "https://regulator-b.gov/i/consumer-protection/keys/2f73", 1392 | "signatureValue": "Piw90D4cFqT/yKd/JGLv...NGFz==" 1393 | }, ... // there will be at least 3 more signatures here 1394 | ] 1395 | } 1396 |1397 | 1398 |
1399 | The use of nextBlock
is unlikely here, it is more
1400 | likely to be prevBlock
and potentially include
1401 | a hash of that event depending on configuration.
1402 |
1410 | 1411 |
1412 | 1413 |1414 | { 1415 | "@context": ["https://w3id.org/web-ledger/v1", "https://w3id.org/dhs/v1"], 1416 | "id": "did:f6ea280f-8011-4502-a29f-464954de3427/blocks/2", 1417 | "type": "LedgerStorageBlock", 1418 | "setObject": [{ 1419 | "id": "https://hhs.gov/vaccinations/6080026", 1420 | "type": ["Credential", "VaccinationCredential"], 1421 | "claim": { 1422 | "id": "did:e277ce82-bf9d-413a-a6fe-fde877fd19b1", 1423 | "vaccination": { 1424 | "type": "IPV", 1425 | "vaccinationDate": "2004-07-17", 1426 | "vaccinationProvider": "Alameda County Hospital, California, USA" 1427 | } 1428 | } 1429 | }], 1430 | "previousBlock": { 1431 | "id": "did:f6ea280f-8011-4502-a29f-464954de3427/blocks/1", 1432 | "hash": "urn:sha256:f04524659baa027ea49e7d0635bc6b1869d3e7d811f6bfefeb3aae1adcae0362" 1433 | }, 1434 | "signature": { 1435 | "type": "RsaSignature2016", 1436 | "created": "2016-10-12T18:37:27Z", 1437 | "creator": "http://ledger.example.com/keys/fema-key-1", 1438 | "signatureValue": "ITv0b9tTIjgBMgu4jUOsuU9Y2t9rsq+rKrbJHfcKWmDQZE1X6VpqKowv3l27WN0w5NyECIkJx6oy94nlM375ivmhQf6iYd6R7IizVBiRiLl3HeNXdaxBpyYMn6OiP8MYVdJt2g5vj+xhP9AadXnRL0TYmE6qH1LtOw42SQtfseQDb8xF1Bsjie7KmKK/G+B1yoKqg1L34NLSAnHpnqRGAen9OEMi0hwBrVD8HIRFkdCehh4T07HRrZe2mwhfY0gOA54j02qWZxidvYUYAV8vax4AhFyk0Vsaibo9yt85uU8Tc8a4e5hjS7nCAya8FMzDd0xEOp1q9MeC5vgJHKz29g==" 1439 | } 1440 | } 1441 |1442 | 1443 |
1444 | { 1445 | "@context": [ 1446 | "https://w3id.org/web-ledger/v1", 1447 | "https://w3id.org/housing/v1", 1448 | ], 1449 | "id": "https://vhda.va.us.gov/ledger-agents/webville/houses/2", 1450 | "type": "LedgerStorageBlock", 1451 | "previousBlock": "https://example-consortium.com/private-ledgers/loans/real-estate/1", 1452 | "setObject": [{ 1453 | "id": "https://vhda.va.us.gov/properties/3829344", 1454 | "propertyAddress": { 1455 | "street": "263 Main Street", 1456 | "locality": "Webville", 1457 | "region": "VA", 1458 | "postalCode": "24736-3726", 1459 | "country": "US" 1460 | }, 1461 | "owner": { 1462 | "name": "Jane Smith", 1463 | "postalAddress": { ... } 1464 | }], 1465 | "signature": { 1466 | "type": "LinkedDataSignature2016", 1467 | "created": "2016-02-22T02:10:21Z", 1468 | "creator": "https://webville.va.us.gov/i/planning-department/keys/1", 1469 | "signatureValue": "cNJGLFqT/d/90D4GFzv...yKPiw==" 1470 | } 1471 | } 1472 |1473 | 1474 |
1475 | { 1476 | "@context": [ 1477 | "https://w3id.org/web-ledger/v1", 1478 | "https://w3id.org/dhs/credentials/v1", 1479 | ], 1480 | "id": "https://example.us.gov/ledger-agents/emergency-response/2", 1481 | "type": "LedgerStorageBlock", 1482 | "previousBlock": "https://example.us.gov/ledger-agents/emergency-response/1", 1483 | "setObject": [{ 1484 | "id": "https://example.us.gov/credentials/234234542", 1485 | "type": ["Credential", "EmergencyResponseCredential"] 1486 | "claim": { 1487 | "id": "did:3f32-23425-53-241442", 1488 | "emsLicense": { 1489 | "id": "FF-37-48573", 1490 | "status": "valid" 1491 | }, 1492 | }], 1493 | "signature": { 1494 | "type": "LinkedDataSignature2016", 1495 | "created": "2016-09-19T17:19:52Z", 1496 | "creator": "https://fema.example.gov/i/credentialing/keys/7f6", 1497 | "signatureValue": "pjeyuFq9idhwHGfGFzv...9fjsk==" 1498 | } 1499 | } 1500 |1501 | 1502 |
1503 | { 1504 | "@context": [ 1505 | "https://w3id.org/web-ledger/v1", 1506 | "https://w3id.org/cryptocurrencies/v1" 1507 | ], 1508 | "id": "bytecoin:block:83ba663df28372718", 1509 | "type": "LedgerStorageBlock", 1510 | "previousBlock": "bytecoin:block:271863df2883ba637", 1511 | "addsObject": [{ 1512 | "transaction": [{ 1513 | "https://w3id.org/bytecoin/v1", 1514 | "source": "bytecoin:2892316f63778", 1515 | "destination": "bytecoin:983bba526fd6", 1516 | "input": [...], // the inputs to the transaction 1517 | "output": [...], // the outputs from the transaction 1518 | "transfer": { 1519 | "amount": "0.3928621", 1520 | "currency": "bytecoin:currency:bco" 1521 | } 1522 | }], ... // there could be hundreds to thousands more of these 1523 | }] 1524 | "signature": { 1525 | "type": "LinkedDataSignature2016", 1526 | "created": "2017-01-24T02:11:16Z", 1527 | "creator": "bytecoin:key:23fa73bb201c738d", 1528 | "signatureValue": "90D4cFqT/yKPiwd/GFzv...NJGL==" 1529 | } 1530 | } 1531 |1532 | 1533 |
1534 | { 1535 | "@context": [ 1536 | "https://w3id.org/web-ledger/v1", 1537 | "https://w3id.org/real-estate/v1" 1538 | ], 1539 | "id": "https://example-consortium.com/private-ledgers/loans/real-estate/2", 1540 | "type": "LedgerStorageBlock", 1541 | "previousBlock": "https://example-consortium.com/private-ledgers/loans/real-estate/1", 1542 | "addsObject": [{ 1543 | "id": "https://example-consortium.com/private-ledgers/loans/real-estate/transactions/238947234", 1544 | "transaction": { 1545 | "source": "lei:HB7FFAZIO0MZ8PP8OE26", // compliant to ISO 17442 standard 1546 | "destination": "lei:PP8OEHB7FFAZIO0MZ826", 1547 | "transfer": { 1548 | "loanId": "lei:FAZIO0PP8OEHB7FMZ826" 1549 | } 1550 | } 1551 | }], 1552 | "signature": [{ 1553 | "type": "LinkedDataSignature2016", 1554 | "created": "2018-04-16T19:34:18Z", 1555 | "creator": "https://regulator-b.gov/i/consumer-protection/keys/2f73", 1556 | "signatureValue": "Piw90D4cFqT/yKd/JGLv...NGFz==" 1557 | }, ... // there will be at least 3 more signatures here 1558 | ] 1559 | } 1560 |1561 | 1562 |
1568 | { 1569 | "@context": "https://w3id.org/web-ledger/v1", 1570 | "id": "did:f6ea280f-8011-4502-a29f-464954de3427/blocks/100", 1571 | "type": "ConsensusBlock", 1572 | "previousBlock": { 1573 | "id": "did:f6ea280f-8011-4502-a29f-464954de3427/blocks/99", 1574 | "hash": "urn:sha256:0877a494ce1705117f917a3af3fc48190b1fdbca04fdba8e995fd6c15fb2fe71" 1575 | }, 1576 | "signature": [{ 1577 | "type": "RsaSignature2016", 1578 | "created": "2016-10-12T19:54:12Z", 1579 | "creator": "https://notary1.example.org/keys/124", 1580 | "signatureValue": "skeJ4...lBUiI858=" 1581 | }, { 1582 | "type": "RsaSignature2016", 1583 | "created": "2016-10-12T19:54:32Z", 1584 | "creator": "https://notary2.example.org/keys/f31", 1585 | "signatureValue": "iamOjOGncO...gRXfsG0=" 1586 | }, { 1587 | "type": "RsaSignature2016", 1588 | "created": "2016-10-12T19:54:56Z", 1589 | "creator": "https://notary3.example.org/keys/35", 1590 | "signatureValue": "cPehH...iI858=" 1591 | }, { 1592 | "type": "RsaSignature2016", 1593 | "created": "2016-10-12T19:54:23Z", 1594 | "creator": "https://notary4.example.org/keys/ugref2", 1595 | "signatureValue": "hMaD22...ONwzsgo=" 1596 | }] 1597 | } 1598 |1599 |
1605 | A checkpoint log is an entry in the ledger that 1606 |
1607 | 1608 |
1609 | Don't really know if checkpoints are /that/ useful without
1610 | prevId
entries. Don't really know if checkpoints
1611 | are that useful at all? Seems to be the only use is a link
1612 | to a compressed/checksummed file?
1613 |
1616 | { 1617 | "@context": "https://w3id.org/web-ledger/v1", 1618 | "id": "https://example.org/ledger-agents/example/6372463", 1619 | "type": "LedgerCheckpointBlock", 1620 | "checkpointLog": "https://example.org/ledger-agents/example/checkpoints/132", 1621 | "checkpointLogHash": "urn:sha256:7fa3b9eaa8d92d2b87abf83d88a92ff23", 1622 | "signature": [{ 1623 | "type": "LinkedDataSignature2016", 1624 | "created": "2018-04-16T19:34:18Z", 1625 | "creator": "https://example.org/i/master/keys/32", 1626 | "signatureValue": "Piw90D4cFqT/yKd/JGLv...NGFz==" 1627 | }, ... // there may be multiple counter-signatures here 1628 | ] 1629 | } 1630 |1631 |
1637 |
1638 | 1639 |1640 | { 1641 | "@context": [ 1642 | "https://w3id.org/web-ledger/v1", 1643 | "https://w3id.org/cryptocurrencies/v1" 1644 | ], 1645 | "id": "https://example.org/ledger-agents/example/5", 1646 | "type": "LedgerStorageBlock", 1647 | "previousBlock": "https://example.org/ledger-agents/example/4", 1648 | "addsObject": [{ 1649 | "transaction": [{ 1650 | "source": "https://example.org/accounts/jane/7", 1651 | "destination": "https://foo.com/accounts/bob/3", 1652 | "remoteLedger": "https://foo.com/ledger-agents/blah/3445", 1653 | "transfer": { 1654 | "amount": "23.45", 1655 | "currency": "USD" 1656 | } 1657 | }], ... // there could be hundreds to thousands more of these 1658 | }] 1659 | "signature": { 1660 | "type": "LinkedDataSignature2016", 1661 | "created": "2017-01-24T02:11:16Z", 1662 | "creator": "bytecoin:key:23fa73bb201c738d", 1663 | "signatureValue": "90D4cFqT/yKPiwd/GFzv...NJGL==" 1664 | } 1665 | } 1666 |1667 | 1668 |
1676 | This specification, a part of the "Credentials on Public/Private 1677 | Linked Ledgers" project, has been funded in part by the United States 1678 | Department of Homeland Security's Science and Technology Directorate under 1679 | contract HSHQDC-16-C-00058. The content of this specification does not 1680 | necessarily reflect the position or the policy of the U.S. Government and 1681 | no official endorsement should be inferred. 1682 |
1683 | 1684 |1685 | The editor would like to thank the Web Payments Community Group and 1686 | the Blockchain Community Group. 1687 |
1688 | 1689 |1690 | Thanks to the following individuals, in order of their first name, for 1691 | their input on the specification: ... 1692 |
1693 | 1694 |91 | The Flex Ledger vocabulary is used to enable Internet-based applications to 92 | build flexible decentralized ledger and consensus systems. 93 |
94 |99 | This document describes a number of classes and properties that can be used to 100 | enable Internet-based applications to build flexible decentralized ledger 101 | and consensus systems. 102 |
103 |104 | This entire document is a work in progress and should be considered in beta 105 | until it is ratified as an official document via the World Wide Web Consortium. 106 |
107 |111 | This is an experimental vocabulary and its use in production systems 112 | is not recommended at this time. 113 |
114 |123 | An event that is used to provide a snapshot in time that can be used to 124 | quickly bootstrap late-joining nodes in a system. Checkpoint events can also 125 | be used as known good points to start from instead of having to download the 126 | entire ledger history. 127 |
128 |
137 | The example below describes a checkpoint event with a checkpoint log located
138 | at https://example.org/ledgers/example/checkpoints/132
whose
139 | contents hash to a SHA-256 value of
140 | 7fa3b9eaa8d92d2b87abf83d88a92ff23
:
141 |
143 | { 144 | "@context": "https://w3id.org/flex/v1", 145 | "id": "https://example.org/ledgers/example/6372463", 146 | "type": "LedgerCheckpointEvent", 147 | "checkpointLog": "https://example.org/ledgers/example/checkpoints/132", 148 | "checkpointLogHash": "urn:sha256:7fa3b9eaa8d92d2b87abf83d88a92ff23", 149 | "signature": [{ 150 | "type": "LinkedDataSignature2016", 151 | "created": "2018-04-16T19:34:18Z", 152 | "creator": "https://example.org/i/master/keys/32", 153 | "signatureValue": "Piw90D4cFqT/yKd/JGLv...NGFz==" 154 | }, ... // there may be multiple counter-signatures here 155 | ] 156 | } 157 |158 |
164 | An event where the network of nodes curating a particular ledger come to an 165 | agreement on the correct state of the ledger. The mechanism used to come to 166 | agreement is configurable. 167 |
168 |177 | The example below describes a consensus event that includes a link to a 178 | previousConsensusEvent, a list of acknowledged events, and a set of signatures 179 | by multiple entities proving that the consensus ballot had a finalized 180 | outcome: 181 |
182 |183 | { 184 | "@context": "https://w3id.org/flex/v1", 185 | "id": "https://example.org/ledgers/example/8239849843", 186 | "type": ["LedgerConsensusEvent", "ProofOfBallot2015"], 187 | "previousConsensusEvent": "https://example.org/ledgers/example/8239848234", 188 | "acknowledgedEvents": [ 189 | "https://example.org/ledgers/example/8239849838", 190 | "https://example.org/ledgers/example/8239849839", 191 | "https://example.org/ledgers/example/8239849840", 192 | "https://example.org/ledgers/example/8239849841", 193 | "https://example.org/ledgers/example/8239849842", 194 | ], 195 | "signature": [{ 196 | "type": "LinkedDataSignature2016", 197 | "created": "2018-04-16T19:34:18Z", 198 | "creator": "https://webville.va.us.gov/i/planning-department/keys/12", 199 | "signatureValue": "4cF/yKd/JPiw90DqTGLv...NGFz==" 200 | }, // other signatures on votes in favor follow... 201 | ] 202 | } 203 |204 |
210 | An event noting that the operational rules of the ledger have changed. This 211 | event is typically only active after the next ConsensusEvent has taken place. 212 |
213 |222 | The example below describes a configuration event for a ledger. The 223 | configuration event states that the storage mechanism for the ledger is a 224 | sequential list and the consensus algorithm requires one valid signature: 225 |
226 |227 | { 228 | "@context": "https://w3id.org/flex/v1", 229 | "id": "https://vhda.va.us.gov/ledgers/webville/houses/1", 230 | "type": "LedgerConfigurationEvent", 231 | "storageMechanism": "SequentialList", 232 | "consensusAlgorithm": { 233 | "type": "ProofOfSignature2016", 234 | "approvedSigner": "https://webville.va.us.gov/i/planning-department", 235 | "minimumSignaturesRequired": 1 236 | }, 237 | "nextEvent": "https://vhda.va.us.gov/ledgers/webville/houses/2", 238 | "signature": { 239 | "type": "LinkedDataSignature2016", 240 | "created": "2016-02-21T02:10:21Z", 241 | "creator": "https://webville.va.us.gov/i/planning-department/keys/1", 242 | "signatureValue": "cNJGLFqT/d/90D4GFzv...yKPiw==" 243 | } 244 | } 245 |246 |
252 | An event noting that a ledger value has changed. Changes to a ledger can be 253 | modifications to the state machine such as the addition of values, removal 254 | of values, or modification of values. 255 |
256 |265 | The example below describes a storage event containing a financial 266 | transaction and a link to the previous ledger event: 267 |
268 |269 | { 270 | "@context": [ 271 | "https://w3id.org/flex/v1", 272 | "https://w3id.org/cryptocurrencies/v1" 273 | ], 274 | "id": "https://example.org/ledgers/example/5", 275 | "type": "LedgerStorageEvent", 276 | "previousEvent": "https://example.org/ledgers/example/4", 277 | "addsObject": [{ 278 | "transaction": [{ 279 | "source": "https://example.org/accounts/jane/7", 280 | "destination": "https://foo.com/accounts/bob/3", 281 | "remoteLedger": "https://foo.com/ledgers/blah/3445", 282 | "transfer": { 283 | "amount": "23.45", 284 | "currency": "USD" 285 | } 286 | }], ... // there could be hundreds to thousands more of these 287 | }] 288 | "signature": { 289 | "type": "LinkedDataSignature2016", 290 | "created": "2017-01-24T02:11:16Z", 291 | "creator": "bytecoin:key:23fa73bb201c738d", 292 | "signatureValue": "90D4cFqT/yKPiwd/GFzv...NJGL==" 293 | } 294 | }295 |
306 | A storage mechanism that combines a 307 | Merkle Tree with a 308 | radix-sorted trie thus 309 | creating a quickly searchable hashtree. Merkle-Patricia Tries are 310 | fully deterministic meaning that re-creating the tree results in the same 311 | root hash and byte-perfect key-value bindings. This data structure 312 | provides O(log(n)) efficiency for inserts, lookups and deletes, and are 313 | simpler to implement and understand. The Ethereum blockchain uses 314 | Merkle-Patricia Tries for storage. 315 |
316 |325 | The example below describes a configuration event where the selected storage 326 | mechanism is a Merkle-Patricia trie: 327 |
328 |329 | { 330 | "@context": [ 331 | "https://w3id.org/flex/v1", 332 | "https://w3id.org/cryptocurrencies/v1" 333 | ], 334 | "id": "lux:entry:37823", 335 | "type": "LedgerConfigurationEvent", 336 | "storageMechanism": "MerklePatriciaTrie", 337 | "consensusAlgorithm": { 338 | "type": "ProofOfBallot2015", 339 | "minimumQuorumPercentage": "0.51", 340 | "minimumVotePercentage": "0.67", 341 | "approvedSigner": [ 342 | "https://regulator-a.gov/i/bank-oversight", 343 | "https://regulator-b.gov/i/consumer-protection", 344 | "https://bank-x.com/i/housing", 345 | "https://bank-y.com/i/corporate-loans", 346 | "https://bank-z.com/i/swaps", 347 | ] 348 | }, 349 | "signature": { 350 | "type": "LinkedDataSignature2016", 351 | "created": "2017-01-24T02:10:21Z", 352 | "creator": "lux:keys:d52aff68923f3b2c8183bd", 353 | "signatureValue": "FqT/yK90D4cPiwd/GFzv...NJGL==" 354 | } 355 | } 356 |357 |
363 | A storage mechanism utilizing the 364 | Merkle Tree 365 | data structure, which enables efficient and secure verification of the 366 | contents of large data structures. The Bitcoin blockchain utilizes Merkle trees 367 | in its implementation. 368 |
369 |378 | The example below describes a ledger storage event where the storage mechanism 379 | is a Merkle tree: 380 |
381 |382 | { 383 | "@context": [ 384 | "https://w3id.org/flex/v1", 385 | "https://w3id.org/cryptocurrencies/v1" 386 | ], 387 | "id": "bytecoin:block:23fa73bb201c738d", 388 | "type": "LedgerConfigurationEvent", 389 | "storageMechanism": "MerkleTree", 390 | "consensusAlgorithm": { 391 | "type": "ProofOfWork2016", 392 | "proofOfWorkAlgorithm": "Bitcoin", 393 | "targetDifficulty": "199312067531.243" 394 | }, 395 | "signature": { 396 | "type": "LinkedDataSignature2016", 397 | "created": "2017-01-24T02:10:21Z", 398 | "creator": "bytecoin:keys:23f3b2c8183bdd52aff689", 399 | "signatureValue": "90D4cFqT/yKPiwd/GFzv...NJGL==" 400 | } 401 | } 402 |403 |
409 | A data structure that stores a sequential list of items, also known as a 410 | linked list. 411 |
412 |421 | The example below describes a ledger configuration event where the storage 422 | mechanism is a sequential list: 423 |
424 |425 | { 426 | "@context": "https://w3id.org/flex/v1", 427 | "id": "https://vhda.va.us.gov/ledgers/webville/houses/1", 428 | "type": "LedgerConfigurationEvent", 429 | "storageMechanism": "SequentialList", 430 | "consensusAlgorithm": { 431 | "type": "ProofOfSignature2016", 432 | "approvedSigner": "https://webville.va.us.gov/i/planning-department", 433 | "minimumSignaturesRequired": 1 434 | }, 435 | "nextEvent": "https://vhda.va.us.gov/ledgers/webville/houses/2", 436 | "signature": { 437 | "type": "LinkedDataSignature2016", 438 | "created": "2016-02-21T02:10:21Z", 439 | "creator": "https://webville.va.us.gov/i/planning-department/keys/1", 440 | "signatureValue": "cNJGLFqT/d/90D4GFzv...yKPiw==" 441 | } 442 | } 443 |444 |
455 | A consensus protocol as described in the 456 | Stellar Consensus Protocol Whitepaper. The Stellar 457 | Consensus Protocol is the first provably safe construction for Federated 458 | Byzantine Agreement. Unlike most existing approaches to consensus, it enjoys 459 | four key properties: 1) decentralized control, 2) flexible trust, 460 | 3) low latency, and 3) asymptotic security. As a Federated Byzantine 461 | Agreement protocol, it guarantees safety in the face of non-rational behavior 462 | and requires only modest computing resources, lowering the barrier to entry. 463 |
464 |475 | The example below describes a consensus mechanism object where the mechanism 476 | is a proof of ballot where at least 51% of the voting members are available 477 | and the minimum vote required to reach consensus is 67%: 478 |
479 |480 | { 481 | "@context": "https://w3id.org/flex/v1", 482 | "type": "ProofOfBallot2015", 483 | "quorum": "0.51", 484 | "minimumVotePercentage": "0.67" 485 | } 486 |487 |
493 | A consensus protocol that proves that a particular amount of effort has been 494 | expended to arrive at a provided answer. For example, Bitcoin's Proof of Work 495 | algorithm proves that a statistically significant amount of hashing computations 496 | have occurred to arrive at an answer. 497 |
498 |
509 | The example below describes a consensus mechanism object where the mechanism
510 | is a Bitcoin-style proof of work with a target difficulty of
511 | 199312067531.243
:
512 |
514 | { 515 | "@context": "https://w3id.org/flex/v1", 516 | "type": "ProofOfWork2016", 517 | "proofOfWorkAlgorithm": "Bitcoin", // double SHA-256 on block hash + nonce < targetDifficulty 518 | "targetDifficulty": "199312067531.243" 519 | } 520 |521 |
527 | A consensus protocol that demonstrates that a certain number of signatures 528 | past a given threshold have been registered. 529 |
530 |541 | The example below describes a consensus mechanism object where the mechanism 542 | is a proof of signature that requires two signatures from the set of 543 | approved signers: 544 |
545 |546 | { 547 | "@context": "https://w3id.org/flex/v1", 548 | "type": "ProofOfSignature2016", 549 | "approvedSigner": [ 550 | "https://fema.example.us.gov/i/ofp", 551 | "https://tsa.example.us.gov/i/vclaims", 552 | "https://dhs.example.us.gov/i/credentialing" 553 | ], 554 | "minimumSignaturesRequired": 2 555 | } 556 |557 |
597 | Denotes that one or more objects have been added as a result of the event. 598 | This property is typically used by LedgerStorageEvents. 599 |
600 |607 | The example below expresses a ledger storage event where an object 608 | describing a real estate loan transfer is added to the ledger. 609 |
610 |611 | { 612 | "@context": [ 613 | "https://w3id.org/flex/v1", 614 | "https://w3id.org/real-estate/v1" 615 | ], 616 | "id": "https://example-consortium.com/private-ledgers/loans/real-estate/2", 617 | "type": "LedgerStorageEvent", 618 | "previousEvent": "https://example-consortium.com/private-ledgers/loans/real-estate/1", 619 | "addsObject": [{ 620 | "id": "https://example-consortium.com/private-ledgers/loans/real-estate/transactions/238947234", 621 | "transaction": { 622 | "source": "lei:HB7FFAZIO0MZ8PP8OE26", // compliant to ISO 17442 standard 623 | "destination": "lei:PP8OEHB7FFAZIO0MZ826", 624 | "transfer": { 625 | "loanId": "lei:FAZIO0PP8OEHB7FMZ826" 626 | } 627 | } 628 | }], 629 | "signature": [{ 630 | "type": "LinkedDataSignature2016", 631 | "created": "2018-04-16T19:34:18Z", 632 | "creator": "https://regulator-b.gov/i/consumer-protection/keys/2f73", 633 | "signatureValue": "Piw90D4cFqT/yKd/JGLv...NGFz==" 634 | }, ... // there will be at least 3 more signatures here 635 | ] 636 | } 637 |638 |
644 | Specifies an entity that is authorized to assert consensus under 645 | permissioned consensus algorithms. It is important to note that the data, 646 | such as public key material, should be stored in the ledger to ensure 647 | long-term auditability of the ledger. 648 |
649 |
656 | The example below describes a ledger configuration event with a proof of
657 | signature consensus algorithm. The proof of signature only requires one
658 | approved signer, which is
659 | https://webville.va.us.gov/i/planning-department
.
660 |
662 | { 663 | "@context": "https://w3id.org/flex/v1", 664 | "id": "https://vhda.va.us.gov/ledgers/webville/houses/1", 665 | "type": "LedgerConfigurationEvent", 666 | "storageMechanism": "SequentialList", 667 | "consensusAlgorithm": { 668 | "type": "ProofOfSignature2016", 669 | "approvedSigner": "https://webville.va.us.gov/i/planning-department", 670 | "minimumSignaturesRequired": 1 671 | }, 672 | "nextEvent": "https://vhda.va.us.gov/ledgers/webville/houses/2", 673 | "signature": { 674 | "type": "LinkedDataSignature2016", 675 | "created": "2016-02-21T02:10:21Z", 676 | "creator": "https://webville.va.us.gov/i/planning-department/keys/1", 677 | "signatureValue": "cNJGLFqT/d/90D4GFzv...yKPiw==" 678 | } 679 | } 680 |681 |
688 | A URL pointing to a log file that when replayed can re-create the current 689 | state of the ledger. 690 |
691 |
698 | The example below expresses a ledger checkpoint event with a checkpointLog
699 | located at https://example.org/ledgers/example/checkpoints/132
.
700 |
702 | { 703 | "@context": "https://w3id.org/flex/v1", 704 | "id": "https://example.org/ledgers/example/6372463", 705 | "type": "LedgerCheckpointEvent", 706 | "checkpointLog": "https://example.org/ledgers/example/checkpoints/132", 707 | "checkpointLogHash": "urn:sha256:7fa3b9eaa8d92d2b87abf83d88a92ff23", 708 | "signature": [{ 709 | "type": "LinkedDataSignature2016", 710 | "created": "2018-04-16T19:34:18Z", 711 | "creator": "https://example.org/i/master/keys/32", 712 | "signatureValue": "Piw90D4cFqT/yKd/JGLv...NGFz==" 713 | }, ... // there may be multiple counter-signatures here 714 | ] 715 | } 716 |717 |
723 | A cryptographic hash of the contents of the checkpointLog that may be 724 | used to ensure data integrity. 725 |
726 |
733 | The example below expresses a ledger checkpoint event with a checkpointLog
734 | located at https://example.org/ledgers/example/checkpoints/132
735 | where the contents of the log should hash to a SHA-256 value of
736 | 7fa3b9eaa8d92d2b87abf83d88a92ff23
.
737 |
739 | { 740 | "@context": "https://w3id.org/flex/v1", 741 | "id": "https://example.org/ledgers/example/6372463", 742 | "type": "LedgerCheckpointEvent", 743 | "checkpointLog": "https://example.org/ledgers/example/checkpoints/132", 744 | "checkpointLogHash": "urn:sha256:7fa3b9eaa8d92d2b87abf83d88a92ff23", 745 | "signature": [{ 746 | "type": "LinkedDataSignature2016", 747 | "created": "2018-04-16T19:34:18Z", 748 | "creator": "https://example.org/i/master/keys/32", 749 | "signatureValue": "Piw90D4cFqT/yKd/JGLv...NGFz==" 750 | }, ... // there may be multiple counter-signatures here 751 | ] 752 | } 753 |754 |
760 | Used to specify a particular consensus algorithm, typically used in a 761 | ConfigurationEvent. 762 |
763 |770 | The example below expresses a proof of signature consensus algorithm. This 771 | information is typically expressed in a ledger configuration event. 772 |
773 |774 | { 775 | "@context": "https://w3id.org/flex/v1", 776 | "consensusAlgorithm": { 777 | "type": "ProofOfSignature2016", 778 | "approvedSigner": [ 779 | "https://fema.example.us.gov/i/ofp", 780 | "https://tsa.example.us.gov/i/vclaims", 781 | "https://dhs.example.us.gov/i/credentialing" 782 | ], 783 | "minimumSignaturesRequired": 2 784 | } 785 | } 786 |787 |
793 | The minimum percentage of members in a particular balloting initiative that 794 | are required to vote in order for the vote to count. 795 |
796 |803 | The example below expresses a ledger configuration event that specifies 804 | a proof of ballot consensus algorithm where the minimum percentage to 805 | achieve quorum is 51%. 806 |
807 |808 | { 809 | "@context": [ 810 | "https://w3id.org/flex/v1", 811 | "https://w3id.org/cryptocurrencies/v1" 812 | ], 813 | "id": "https://example-consortium.com/private-ledgers/loans/real-estate/1", 814 | "type": "LedgerConfigurationEvent", 815 | "storageMechanism": "SequentialList", 816 | "consensusAlgorithm": { 817 | "type": "ProofOfBallot2015", 818 | "minimumQuorumPercentage": "0.51", 819 | "minimumVotePercentage": "0.67", 820 | "approvedSigner": [ 821 | "https://regulator-a.gov/i/bank-oversight", 822 | "https://regulator-b.gov/i/consumer-protection", 823 | "https://bank-x.com/i/housing", 824 | "https://bank-y.com/i/corporate-loans", 825 | "https://bank-z.com/i/swaps", 826 | ] 827 | }, 828 | "signature": [{ 829 | "type": "LinkedDataSignature2016", 830 | "created": "2018-04-16T19:34:18Z", 831 | "creator": "https://regulator-b.gov/i/consumer-protection/keys/2f73", 832 | "signatureValue": "Piw90D4cFqT/yKd/JGLv...NGFz==" 833 | }, ... // there will be at least 3 more signatures here 834 | ] 835 | } 836 |837 |
844 | The minimum number of signatures required to bind a particular decision made 845 | in a ledger. 846 |
847 |854 | The example below expresses a ledger configuration event specifying a 855 | proof of signature consensus algorithm where only one signature is required 856 | from the set of approved signers. 857 |
858 |859 | { 860 | "@context": "https://w3id.org/flex/v1", 861 | "id": "https://vhda.va.us.gov/ledgers/webville/houses/1", 862 | "type": "LedgerConfigurationEvent", 863 | "storageMechanism": "SequentialList", 864 | "consensusAlgorithm": { 865 | "type": "ProofOfSignature2016", 866 | "approvedSigner": "https://webville.va.us.gov/i/planning-department", 867 | "minimumSignaturesRequired": 1 868 | }, 869 | "nextEvent": "https://vhda.va.us.gov/ledgers/webville/houses/2", 870 | "signature": { 871 | "type": "LinkedDataSignature2016", 872 | "created": "2016-02-21T02:10:21Z", 873 | "creator": "https://webville.va.us.gov/i/planning-department/keys/1", 874 | "signatureValue": "cNJGLFqT/d/90D4GFzv...yKPiw==" 875 | } 876 | } 877 |878 |
884 | The minimum percentage of votes in an election to carry a particular 885 | motion under consideration. 886 |
887 |894 | The example below expresses a ledger configuration event specifying a 895 | proof of ballot consensus algorithm where 67% of the vote is required to 896 | pass a motion. 897 |
898 |899 | { 900 | "@context": [ 901 | "https://w3id.org/flex/v1", 902 | "https://w3id.org/cryptocurrencies/v1" 903 | ], 904 | "id": "https://example-consortium.com/private-ledgers/loans/real-estate/1", 905 | "type": "LedgerConfigurationEvent", 906 | "storageMechanism": "SequentialList", 907 | "consensusAlgorithm": { 908 | "type": "ProofOfBallot2015", 909 | "minimumQuorumPercentage": "0.51", 910 | "minimumVotePercentage": "0.67", 911 | "approvedSigner": [ 912 | "https://regulator-a.gov/i/bank-oversight", 913 | "https://regulator-b.gov/i/consumer-protection", 914 | "https://bank-x.com/i/housing", 915 | "https://bank-y.com/i/corporate-loans", 916 | "https://bank-z.com/i/swaps", 917 | ] 918 | }, 919 | "signature": [{ 920 | "type": "LinkedDataSignature2016", 921 | "created": "2018-04-16T19:34:18Z", 922 | "creator": "https://regulator-b.gov/i/consumer-protection/keys/2f73", 923 | "signatureValue": "Piw90D4cFqT/yKd/JGLv...NGFz==" 924 | }, ... // there will be at least 3 more signatures here 925 | ] 926 | } 927 |928 |
935 | The next event in a ledger. It is not always possible to know what the 936 | next event is for ledgers of a certain type. 937 |
938 |
945 | The example below expresses a ledger event where the next event
946 | (https://vhda.va.us.gov/ledgers/webville/houses/2
) is known.
947 |
949 | { 950 | "@context": "https://w3id.org/flex/v1", 951 | "id": "https://vhda.va.us.gov/ledgers/webville/houses/1", 952 | "type": "LedgerConfigurationEvent", 953 | "storageMechanism": "SequentialList", 954 | "consensusAlgorithm": { 955 | "type": "ProofOfSignature2016", 956 | "approvedSigner": "https://webville.va.us.gov/i/planning-department", 957 | "minimumSignaturesRequired": 1 958 | }, 959 | "nextEvent": "https://vhda.va.us.gov/ledgers/webville/houses/2", 960 | "signature": { 961 | "type": "LinkedDataSignature2016", 962 | "created": "2016-02-21T02:10:21Z", 963 | "creator": "https://webville.va.us.gov/i/planning-department/keys/1", 964 | "signatureValue": "cNJGLFqT/d/90D4GFzv...yKPiw==" 965 | } 966 | } 967 |968 |
975 | The previous event in a ledger. This is typically useful when auditing a 976 | ledger to ensure that its history is valid. 977 |
978 |
985 | The example below expresses a ledger event where the previous event
986 | can be accessed at
987 | https://example-consortium.com/private-ledgers/loans/real-estate/1
.
988 |
990 | { 991 | "@context": [ 992 | "https://w3id.org/flex/v1", 993 | "https://w3id.org/housing/v1", 994 | ], 995 | "id": "https://vhda.va.us.gov/ledgers/webville/houses/2", 996 | "type": "LedgerStorageEvent", 997 | "previousEvent": "https://example-consortium.com/private-ledgers/loans/real-estate/1", 998 | "replacesObject": [{ 999 | "id": "https://vhda.va.us.gov/properties/3829344", 1000 | "propertyAddress": { 1001 | "street": "263 Main Street", 1002 | "locality": "Webville", 1003 | "region": "VA", 1004 | "postalCode": "24736-3726", 1005 | "country": "US" 1006 | }, 1007 | "owner": { 1008 | "name": "Jane Smith", 1009 | "postalAddress": { ... } 1010 | }], 1011 | "signature": { 1012 | "type": "LinkedDataSignature2016", 1013 | "created": "2016-02-22T02:10:21Z", 1014 | "creator": "https://webville.va.us.gov/i/planning-department/keys/1", 1015 | "signatureValue": "cNJGLFqT/d/90D4GFzv...yKPiw==" 1016 | } 1017 | } 1018 |1019 |
1026 | This property is used to specify the type of proof of work algorithm that 1027 | the ledger expects to be executed in order to reach consensus. 1028 |
1029 |
1036 | The example below expresses a proof of work consensus algorithm where the
1037 | specific algorithm is Bitcoin
. Note that this property requires a
1038 | URL and Bitcoin
is an alias for a URL like
1039 | https://example.com/algorithms/Bitcoin
.
1040 |
1042 | { 1043 | "@context": [ "https://w3id.org/flex/v1", "https://w3id.org/cryptocurrencies/v1" ], 1044 | "type": "ProofOfWork2016", 1045 | "proofOfWorkAlgorithm": "Bitcoin", 1046 | "targetDifficulty": "199312067531.243" 1047 | } 1048 |1049 |
1055 | Used to specify the set of objects to remove during a StorageEvent. 1056 |
1057 |1064 | The example below expresses a ledger storage event where an object 1065 | describing a real estate property is removed from the ledger. Note that a 1066 | removal doesn't remove the object from history, it only removes the object 1067 | from the active state in the state machine. 1068 |
1069 |1070 | { 1071 | "@context": [ 1072 | "https://w3id.org/flex/v1", 1073 | "https://w3id.org/housing/v1", 1074 | ], 1075 | "id": "https://vhda.va.us.gov/ledgers/webville/houses/2", 1076 | "type": "LedgerStorageEvent", 1077 | "previousEvent": "https://example-consortium.com/private-ledgers/loans/real-estate/1", 1078 | "removesObject": [{ 1079 | "id": "https://vhda.va.us.gov/properties/3829344", 1080 | "propertyAddress": { 1081 | "street": "263 Main Street", 1082 | "locality": "Webville", 1083 | "region": "VA", 1084 | "postalCode": "24736-3726", 1085 | "country": "US" 1086 | }, 1087 | "owner": { 1088 | "name": "Jane Smith", 1089 | "postalAddress": { ... } 1090 | }], 1091 | "signature": { 1092 | "type": "LinkedDataSignature2016", 1093 | "created": "2016-02-22T02:10:21Z", 1094 | "creator": "https://webville.va.us.gov/i/planning-department/keys/1", 1095 | "signatureValue": "cNJGLFqT/d/90D4GFzv...yKPiw==" 1096 | } 1097 | } 1098 |1099 |
1105 | Used to specify the set of objects to replace during a StorageEvent. 1106 |
1107 |1114 | The example below expresses a ledger storage event where an object 1115 | describing a real estate property is replaced with new information. 1116 |
1117 |1118 | { 1119 | "@context": [ 1120 | "https://w3id.org/flex/v1", 1121 | "https://w3id.org/housing/v1", 1122 | ], 1123 | "id": "https://vhda.va.us.gov/ledgers/webville/houses/2", 1124 | "type": "LedgerStorageEvent", 1125 | "previousEvent": "https://example-consortium.com/private-ledgers/loans/real-estate/1", 1126 | "replacesObject": [{ 1127 | "id": "https://vhda.va.us.gov/properties/3829344", 1128 | "propertyAddress": { 1129 | "street": "263 Main Street", 1130 | "locality": "Webville", 1131 | "region": "VA", 1132 | "postalCode": "24736-3726", 1133 | "country": "US" 1134 | }, 1135 | "owner": { 1136 | "name": "Jane Smith", 1137 | "postalAddress": { ... } 1138 | }], 1139 | "signature": { 1140 | "type": "LinkedDataSignature2016", 1141 | "created": "2016-02-22T02:10:21Z", 1142 | "creator": "https://webville.va.us.gov/i/planning-department/keys/1", 1143 | "signatureValue": "cNJGLFqT/d/90D4GFzv...yKPiw==" 1144 | } 1145 | } 1146 |1147 |
1154 | Denotes the type of storage mechanism that should be used for this ledger. 1155 | These storage mechanisms often have qualities that the ledger depends on 1156 | for integrity checking, storage efficiency, or other qualities that are 1157 | important to the ledger application. 1158 |
1159 |1166 | The example below expresses a ledger configuration event where the storage 1167 | mechanism is a sequential list. 1168 |
1169 |1170 | { 1171 | "@context": "https://w3id.org/flex/v1", 1172 | "id": "https://vhda.va.us.gov/ledgers/webville/houses/1", 1173 | "type": "LedgerConfigurationEvent", 1174 | "storageMechanism": "SequentialList", 1175 | "consensusAlgorithm": { 1176 | "type": "ProofOfSignature2016", 1177 | "approvedSigner": "https://webville.va.us.gov/i/planning-department", 1178 | "minimumSignaturesRequired": 1 1179 | }, 1180 | "nextEvent": "https://vhda.va.us.gov/ledgers/webville/houses/2", 1181 | "signature": { 1182 | "type": "LinkedDataSignature2016", 1183 | "created": "2016-02-21T02:10:21Z", 1184 | "creator": "https://webville.va.us.gov/i/planning-department/keys/1", 1185 | "signatureValue": "cNJGLFqT/d/90D4GFzv...yKPiw==" 1186 | } 1187 | } 1188 |1189 |
1196 | A property that specifies how difficult a particular proof of work should be. 1197 | The value is dependent on the proofOfWorkAlgorithm property. 1198 |
1199 |
1206 | The example below expresses a Bitcoin proof of work consensus algorithm where
1207 | the target difficulty is 199312067531.243
.
1208 |
1210 | { 1211 | "@context": "https://w3id.org/flex/v1", 1212 | "type": "ProofOfWork2016", 1213 | "proofOfWorkAlgorithm": "Bitcoin", 1214 | "targetDifficulty": "199312067531.243" 1215 | } 1216 |1217 |
1252 | This specification, a part of the "Credentials on Public/Private 1253 | Linked Ledgers" project, has been funded in part by the United States 1254 | Department of Homeland Security's Science and Technology Directorate under 1255 | contract HSHQDC-16-C-00058. The content of this specification does not 1256 | necessarily reflect the position or the policy of the U.S. Government and 1257 | no official endorsement should be inferred. 1258 |
1259 |