├── .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 | The Web Ledger Protocol 1.0 5 | 6 | 11 | 12 | 13 | 14 | 97 | 102 | 103 | 104 | 105 |
106 |

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 |
120 | 121 |
122 | 123 |

There are a number of ways that one may participate in the development of 124 | this specification:

125 | 126 | 139 |
140 | 141 |
142 |

Introduction

143 | 144 |

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 |
154 | 155 |
156 | A decentralized system can be viewed as a state machine where events 157 | transition the machine from one state to the next. 158 |
159 |
160 | 161 |

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 |
172 | 173 |
174 | There may be many different types of events that trigger state changes in 175 | a decentralized system. 176 |
177 |
178 | 179 |

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 |
186 | 187 |
188 | As the system processes each type of event, its underlying state changes. 189 |
190 |
191 | 192 |

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 |
199 | 200 |
201 | Events are typically packaged into blocks for the purposes of storage 202 | efficiency. 203 |
204 |
205 | 206 |

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 |
226 | 227 |
228 | A cryptographic ledger is a log of states and events that can be independently 229 | verified using cryptography. 230 |
231 |
232 | 233 |

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 |

244 | 245 |
246 | The ecosystem described by this specification consists of a 247 | ledger agent, a ledger node, and a ledger. 248 |
249 |
250 | 251 | 252 |

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 |
262 |

About this Document

263 | 264 |

265 | This document is a detailed specification for ... 266 |

267 | 268 | 274 |
275 |
276 |

How this Document is Organized

277 | 278 |

279 | This document is organized as follows: 280 |

281 | 282 | 306 |
307 |
308 | 309 |
310 |

Terminology

311 | 312 | 313 |
314 |
block
315 |
316 | A data structure that contains one or more ledger events. 317 |
318 |
blockchain
319 |
320 | A ledger containing a series of blocks where the ordering of 321 | the blocks can be mathematically proven to be correct. 322 |
323 |
consensus algorithm
324 |
325 | An algorithm that enables multiple nodes in a network to make a decision 326 | in a deterministic fashion. 327 |
328 |
cryptographic ledger
329 |
330 | A method of recording changes in a state machine where the 331 | accuracy of the ledger can be mathematically proven to be correct. 332 |
333 |
decentralized system
334 |
335 | A system in which lower level components operate on local information to 336 | accomplish global goals. For example, an ant colony is a decentralized system 337 | as there is no central control determining when food must be collected or 338 | how new tunnels should be excavated. 339 |
340 |
decentralized ledger
341 |
342 | A cryptographic ledger that uses a consensus algorithm that 343 | enables a network of ledger nodes to come to consensus in a 344 | decentralized yet deterministic fashion. 345 |
346 |
event
347 |
348 | Any data recorded in a ledger that changes the 349 | state machine. 350 |
351 |
genesis event
352 |
353 | The first entry in a ledger. This event may be placed into the first 354 | block, which is typically called the 355 | genesis block. 356 |
357 |
ledger agent
358 |
359 | A software program that instructs a ledger node to perform specific 360 | actions such as reading or writing data. 361 |
362 |
ledger node
363 |
364 | A software program that reads and writes from particular instance of 365 | a ledger by executing algorithms according to the rules of the ledger. 366 | The ledger node may be instructed to perform actions on the ledger by a 367 | ledger agent. 368 |
369 |
state machine
370 |
371 | A system that when given a particular input changes from one internal state 372 | to another internal state. For example, a computer system that operates a 373 | light bulb starts with the light state set to off. When an input to turn 374 | the light on is given, the internal computer system state sets the light 375 | state to on, thus illuminating the light bulb. 376 |
377 |
378 | 379 |
380 | 381 | 382 | 383 |
384 |

Data Model

385 | 386 |

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 |
408 |

Blocks

409 | 410 |

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 |
419 | 420 |
421 |

Configuration Block

422 | 423 |

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 |

463 | 464 |

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 |

469 | 470 |
 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 |

498 | 499 |
500 | 501 |
502 |

Storage Block

503 | 504 |

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 |

533 | 534 |
535 | 536 |
537 |

Consensus Block

538 | 539 |

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 |

573 | 574 |
575 | 576 |
577 |

Checkpoint Block

578 | 579 |

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 |

606 | 607 |

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 |
615 | 616 |
617 | 618 |
619 |

Ledger Agent HTTP API

620 | 621 |

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 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 |
ServiceExample URLDescription
ledgerAgentCreateServicePOST /ledger-agentsCreate a ledger agent.
ledgerAgentListServiceGET /ledger-agentsGet all ledger agents.
ledgerAgentStatusServiceGET /ledger-agents/{agent}Get the current status of the ledger agent.
ledgerEventServicePOST /ledger-agents/{agent}/eventsRequest the addition of an event to ledger.
ledgerBlockServiceGET /ledger-agents/{agent}/blocksGet a specific block from the ledger.
ledgerQueryServiceGET /ledger-agents/{agent}/queryQuery the current state of the ledger.
680 | 681 |
682 |

Discovering Service Endpoints

683 | 684 |

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 |

688 | 689 |
 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 |

718 | 719 |
 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 |
730 | 731 |
732 |

Agent Create Service

733 | 734 |

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 |

740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 |
HTTP StatusDescription
201 750 | Ledger creation was successful. The HTTP Location header will 751 | contain the URL for the newly created ledger. 752 |
400Ledger creation failed.
409A duplicate ledger exists.
764 | 765 |

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 |
825 | 826 |
827 |

Agent List Service

828 | 829 |

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 |

834 | 835 | 836 | 837 | 838 | 839 | 840 | 841 | 842 | 843 | 846 | 847 | 848 | 849 | 852 | 853 | 854 |
HTTP StatusDescription
200 844 | The list of ledgers was found and will be returned in the body of the response. 845 |
404 850 | The list of ledgers was not found at the given URL. 851 |
855 | 856 |

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 |
929 | 930 |
931 |

Agent Status Service

932 | 933 |

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 |

938 | 939 | 940 | 941 | 942 | 943 | 944 | 945 | 946 | 947 | 950 | 951 | 952 | 953 | 956 | 957 | 958 |
HTTP StatusDescription
200 948 | The ledger agent status was found and will be returned in the body of the response. 949 |
404 954 | The ledger agent status was not found at the given URL. 955 |
959 | 960 |

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 |
1026 | 1027 |
1028 |

Ledger Append Service

1029 | 1030 |

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 |

1036 | 1037 | 1038 | 1039 | 1040 | 1041 | 1042 | 1043 | 1044 | 1045 | 1048 | 1049 | 1050 | 1051 | 1054 | 1055 | 1056 | 1057 | 1060 | 1061 | 1062 |
HTTP StatusDescription
201 1046 | The ledger block was sucessfully appended. 1047 |
400 1052 | The ledger block failed to be appended. 1053 |
409 1058 | The ledger block with the given identifier already exists. 1059 |
1063 | 1064 |

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 |
1117 | 1118 |
1119 |

Ledger Block Service

1120 | 1121 |

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 |

1127 | 1128 | 1129 | 1130 | 1131 | 1132 | 1133 | 1134 | 1135 | 1136 | 1139 | 1140 | 1141 | 1142 | 1145 | 1146 | 1147 |
HTTP StatusDescription
200 1137 | Retrieval of the ledger block was successful. 1138 |
404 1143 | The ledger block was not found at the given URL. 1144 |
1148 | 1149 |

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 |
1209 | 1210 | 1211 |
1212 |

Ledger Query Service

1213 | 1214 |

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 |

1219 | 1220 | 1221 | 1222 | 1223 | 1224 | 1225 | 1226 | 1227 | 1228 | 1231 | 1232 | 1233 | 1234 | 1237 | 1238 | 1239 | 1240 | 1243 | 1244 | 1245 |
HTTP StatusDescription
200 1229 | Retrieval of the latest state machine object was successful. 1230 |
400 1235 | The query was malformed. 1236 |
404 1241 | The given state machine object was not found. 1242 |
1246 | 1247 |

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 |
1278 | 1279 |
1280 | 1281 |
1282 |

Industry-specific Examples

1283 | 1284 |
1285 |

Configuring the Ledger

1286 | 1287 |
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 |

1403 | 1404 |
1405 | 1406 |
1407 |

Storing Data in the Ledger

1408 | 1409 |

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 |
1563 | 1564 |
1565 |

Recording Consensus

1566 | 1567 |
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 |
1600 | 1601 |
1602 |

Checkpointing Ledger State

1603 | 1604 |

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 |

1614 | 1615 |
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 |
1632 | 1633 |
1634 |

Linking to Other Ledgers

1635 | 1636 |

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 |
1669 | 1670 |
1671 | 1672 |
1673 |

Acknowledgements

1674 | 1675 |

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 |
1695 | 1696 | 1697 | 1698 | -------------------------------------------------------------------------------- /js/browser.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const contexts = exports.contexts = new Map(); 4 | const constants = exports.constants = require('./constants.js'); 5 | 6 | contexts.set( 7 | constants.WEB_LEDGER_CONTEXT_V1_URL, 8 | require('../contexts/webledger-v1.jsonld')); 9 | -------------------------------------------------------------------------------- /js/constants.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.WEB_LEDGER_CONTEXT_V1_URL = 'https://w3id.org/webledger/v1'; 4 | -------------------------------------------------------------------------------- /js/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const constants = require('./constants'); 4 | const fs = require('fs'); 5 | const path = require('path'); 6 | 7 | exports.constants = constants; 8 | const contexts = exports.contexts = new Map(); 9 | 10 | function _read(_path) { 11 | return JSON.parse( 12 | fs.readFileSync( 13 | path.join(__dirname, _path), 14 | {encoding: 'utf8'})); 15 | } 16 | 17 | contexts.set( 18 | constants.WEB_LEDGER_CONTEXT_V1_URL, 19 | _read('../contexts/webledger-v1.jsonld')); 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web-ledger-context", 3 | "version": "5.0.1-0", 4 | "description": "Web Ledger Context", 5 | "main": "js", 6 | "module": "./dist/module.js", 7 | "files": [ 8 | "contexts", 9 | "dist/module.js", 10 | "js/constants.js", 11 | "js/index.js" 12 | ], 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/w3c/web-ledger" 16 | }, 17 | "bugs": { 18 | "url": "https://github.com/w3c/web-ledger/issues" 19 | }, 20 | "homepage": "https://github.com/w3c/web-ledger#readme", 21 | "devDependencies": { 22 | "json-loader": "^0.5.7", 23 | "rollup": "^1.11.3", 24 | "rollup-plugin-commonjs": "^9.3.4", 25 | "webpack": "^4.30.0", 26 | "webpack-cli": "^3.3.2" 27 | }, 28 | "scripts": { 29 | "prepublish": "npm run build", 30 | "build": "webpack && rollup -c" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import commonjs from 'rollup-plugin-commonjs'; 2 | 3 | export default { 4 | input: 'dist/main.js', 5 | output: { 6 | file: 'dist/module.js', 7 | format: 'esm' 8 | }, 9 | plugins: [ 10 | commonjs({ 11 | // explicitly list exports otherwise only have 'default' 12 | namedExports: { 13 | 'dist/main.js': ['contexts', 'constants'] 14 | } 15 | }) 16 | ] 17 | }; 18 | -------------------------------------------------------------------------------- /spec.css: -------------------------------------------------------------------------------- 1 | ol.algorithm { counter-reset:numsection; list-style-type: none; } 2 | ol.algorithm li { margin: 0.5em 0; } 3 | ol.algorithm li:before { font-weight: bold; counter-increment: numsection; content: counters(numsection, ".") ") "; } 4 | 5 | -------------------------------------------------------------------------------- /utils.js: -------------------------------------------------------------------------------- 1 | // We should be able to remove terms that are not actually 2 | // referenced from the common definitions 3 | var termNames = [] ; 4 | 5 | function restrictReferences(utils, content) { 6 | var base = document.createElement("div"); 7 | base.innerHTML = content; 8 | 9 | // strategy: Traverse the content finding all of the terms defined 10 | $.each(base.querySelectorAll("dfn"), function(i, item) { 11 | var $t = $(item) ; 12 | var titles = $t.getDfnTitles(); 13 | var n = $t.makeID("dfn", titles[0]); 14 | if (n) { 15 | termNames[n] = $t.parent() ; 16 | } 17 | }); 18 | 19 | // add a handler to come in after all the definitions are resolved 20 | 21 | respecEvents.sub('end', function(message) { 22 | if (message == 'core/link-to-dfn') { 23 | // all definitions are linked 24 | $("a.internalDFN").each(function () { 25 | var $item = $(this) ; 26 | var r = $item.attr('href').replace(/^#/,"") ; 27 | if (termNames[r]) { 28 | delete termNames[r] ; 29 | } 30 | }); 31 | // delete any terms that were not referenced. 32 | Object.keys(termNames).forEach(function(term) { 33 | var $p = $("#"+term) ; 34 | if ($p) { 35 | var tList = $p.getDfnTitles(); 36 | $p.parent().next().remove(); 37 | $p.remove() ; 38 | tList.forEach(function( item ) { 39 | if (respecConfig.definitionMap[item]) { 40 | delete respecConfig.definitionMap[item]; 41 | } 42 | }); 43 | } 44 | }); 45 | } 46 | }); 47 | 48 | return (base.innerHTML); 49 | } -------------------------------------------------------------------------------- /vocabulary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The Flex Vocabulary 5 | 6 | 11 | 12 | 82 | 83 | 88 | 89 |
90 |

91 | The Flex Ledger vocabulary is used to enable Internet-based applications to 92 | build flexible decentralized ledger and consensus systems. 93 |

94 |
95 | 96 |
97 |

Introduction

98 |

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 |
108 | 109 |
110 |

111 | This is an experimental vocabulary and its use in production systems 112 | is not recommended at this time. 113 |

114 |
115 | 116 |
117 |

Event Classes

118 | 119 |
121 |

CheckpointEvent

122 |

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 |
129 |
Status
130 |
unstable
131 |
Parent Class
132 |
owl:Thing
133 |
Expected properties
134 |
checkpointLog, checkpointLogHash, signature
135 |
136 |

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 |

142 |
 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 |
159 | 160 |
162 |

ConsensusEvent

163 |

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 |
169 |
Status
170 |
unstable
171 |
Parent Class
172 |
owl:Thing
173 |
Expected properties
174 |
previousConsensusEvent, acknowledgedEvents, signature
175 |
176 |

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 |
205 | 206 |
208 |

ConfigurationEvent

209 |

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 |
214 |
Status
215 |
unstable
216 |
Parent Class
217 |
owl:Thing
218 |
Expected properties
219 |
storageMechanism, consensusAlgorithm, signature
220 |
221 |

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 |
247 | 248 |
250 |

StorageEvent

251 |

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 |
257 |
Status
258 |
unstable
259 |
Parent Class
260 |
owl:Thing
261 |
Expected properties
262 |
addsObject, removesObject, replacesObject, signature
263 |
264 |

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 |
296 | 297 |
298 | 299 |
300 |

Storage Classes

301 | 302 |
304 |

MerklePatriciaTrie

305 |

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 |
317 |
Status
318 |
unstable
319 |
Parent Class
320 |
owl:Thing
321 |
Used by
322 |
storageMechanism
323 |
324 |

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 |
358 | 359 |
361 |

MerkleTree

362 |

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 |
370 |
Status
371 |
unstable
372 |
Parent Class
373 |
owl:Thing
374 |
Used by
375 |
storageMechanism
376 |
377 |

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 |
404 | 405 |
407 |

SequentialList

408 |

409 | A data structure that stores a sequential list of items, also known as a 410 | linked list. 411 |

412 |
413 |
Status
414 |
unstable
415 |
Parent Class
416 |
owl:Thing
417 |
Used by
418 |
storageMechanism
419 |
420 |

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 |
445 | 446 |
447 | 448 |
449 |

Proof Classes

450 | 451 |
453 |

ProofOfBallot2015

454 |

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 |
465 |
Status
466 |
unstable
467 |
Parent Class
468 |
owl:Thing
469 |
Used by
470 |
consensusAlgorithm
471 |
Expected properties
472 |
quorum, minimumVotePercentage
473 |
474 |

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 |
488 | 489 |
491 |

ProofOfWork2016

492 |

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 |
499 |
Status
500 |
unstable
501 |
Parent Class
502 |
owl:Thing
503 |
Used by
504 |
consensusAlgorithm
505 |
Expected properties
506 |
targetDifficulty, proofOfWorkAlgorithm
507 |
508 |

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 |

513 |
 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 |
522 | 523 |
525 |

ProofOfSignature2016

526 |

527 | A consensus protocol that demonstrates that a certain number of signatures 528 | past a given threshold have been registered. 529 |

530 |
531 |
Status
532 |
unstable
533 |
Parent Class
534 |
owl:Thing
535 |
Used by
536 |
consensusAlgorithm
537 |
Expected properties
538 |
minimumSignaturesRequired, approvedSigner
539 |
540 |

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 |
558 | 559 | 587 | 588 |
589 | 590 |
591 |

Properties

592 | 593 |
595 |

addsObject

596 |

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 |
601 |
Status
602 |
unstable
603 |
Range
604 |
Thing
605 |
606 |

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 |
639 | 640 |
642 |

approvedSigner

643 |

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 |
650 |
Status
651 |
unstable
652 |
Range
653 |
URL
654 |
655 |

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 |

661 |
 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 |
682 | 683 | 684 |
686 |

checkpointLog

687 |

688 | A URL pointing to a log file that when replayed can re-create the current 689 | state of the ledger. 690 |

691 |
692 |
Status
693 |
unstable
694 |
Range
695 |
URL
696 |
697 |

698 | The example below expresses a ledger checkpoint event with a checkpointLog 699 | located at https://example.org/ledgers/example/checkpoints/132. 700 |

701 |
 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 |
718 | 719 |
721 |

checkpointLogHash

722 |

723 | A cryptographic hash of the contents of the checkpointLog that may be 724 | used to ensure data integrity. 725 |

726 |
727 |
Status
728 |
unstable
729 |
Range
730 |
URI
731 |
732 |

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 |

738 |
 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 |
755 | 756 |
758 |

consensusAlgorithm

759 |

760 | Used to specify a particular consensus algorithm, typically used in a 761 | ConfigurationEvent. 762 |

763 |
764 |
Status
765 |
unstable
766 |
Range
767 |
ConsensusAlgorithm
768 |
769 |

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 |
788 | 789 |
791 |

minimumQuorumPercentage

792 |

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 |
797 |
Status
798 |
unstable
799 |
Range
800 |
xsd:string
801 |
802 |

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 |
838 | 839 | 840 |
842 |

minimumSignaturesRequired

843 |

844 | The minimum number of signatures required to bind a particular decision made 845 | in a ledger. 846 |

847 |
848 |
Status
849 |
unstable
850 |
Range
851 |
xsd:positiveInteger
852 |
853 |

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 |
879 | 880 |
882 |

minimumVotePercentage

883 |

884 | The minimum percentage of votes in an election to carry a particular 885 | motion under consideration. 886 |

887 |
888 |
Status
889 |
unstable
890 |
Range
891 |
xsd:string
892 |
893 |

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 |
929 | 930 | 931 |
933 |

nextEvent

934 |

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 |
939 |
Status
940 |
unstable
941 |
Range
942 |
URL
943 |
944 |

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 |

948 |
 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 |
969 | 970 | 971 |
973 |

previousEvent

974 |

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 |
979 |
Status
980 |
unstable
981 |
Range
982 |
URL
983 |
984 |

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 |

989 |
 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 |
1020 | 1021 | 1022 |
1024 |

proofOfWorkAlgorithm

1025 |

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 |
1030 |
Status
1031 |
unstable
1032 |
Range
1033 |
URI
1034 |
1035 |

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 |

1041 |
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 |
1050 | 1051 |
1053 |

removesObject

1054 |

1055 | Used to specify the set of objects to remove during a StorageEvent. 1056 |

1057 |
1058 |
Status
1059 |
unstable
1060 |
Range
1061 |
Thing
1062 |
1063 |

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 |
1100 | 1101 |
1103 |

replacesObject

1104 |

1105 | Used to specify the set of objects to replace during a StorageEvent. 1106 |

1107 |
1108 |
Status
1109 |
unstable
1110 |
Range
1111 |
Thing
1112 |
1113 |

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 |
1148 | 1149 | 1150 |
1152 |

storageMechanism

1153 |

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 |
1160 |
Status
1161 |
unstable
1162 |
Range
1163 |
URI
1164 |
1165 |

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 |
1190 | 1191 | 1192 |
1194 |

targetDifficulty

1195 |

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 |
1200 |
Status
1201 |
unstable
1202 |
Range
1203 |
xsd:string
1204 |
1205 |

1206 | The example below expresses a Bitcoin proof of work consensus algorithm where 1207 | the target difficulty is 199312067531.243. 1208 |

1209 |
1210 | {
1211 |   "@context": "https://w3id.org/flex/v1",
1212 |   "type": "ProofOfWork2016",
1213 |   "proofOfWorkAlgorithm": "Bitcoin",
1214 |   "targetDifficulty": "199312067531.243"
1215 | }
1216 |         
1217 |
1218 | 1219 | 1244 | 1245 |
1246 | 1247 | 1248 |
1249 |

Acknowledgements

1250 | 1251 |

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 |
1260 | 1261 | 1262 | 1263 | 1264 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | output: { 3 | libraryTarget: 'commonjs' 4 | }, 5 | mode: 'production', 6 | entry: './js/browser.js', 7 | module: { 8 | rules: [ 9 | { 10 | test: /\.jsonld$/, 11 | loader: 'json-loader' 12 | } 13 | ] 14 | } 15 | }; 16 | --------------------------------------------------------------------------------