Difference between revisions of "How It Works"
(Created page with "<div><br></div><div>Category:Documentation</div>") |
|||
| (4 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
| − | <div><br></div><div>[[Category:Documentation]]</div> | + | <div> |
| + | == Overview == | ||
| + | A jig is a JavaScript object that Run syncs with the blockchain. All of its code and method calls are stored on-chain in op_return metadata. Run can reconstruct the state of jigs by loading the code and replaying every method call, but usually intermediate states are cached by indexers. Most jigs are paired with a Bitcoin output so that only the owner of that output can make changes to the jig. All updates taken together form a transaction chain that enables consensus through user verification. This design is similar to other Layer-2 UTXO-based token systems because miners don't verify the JavaScript code. If anyone publishes an incorrect update, it not only destroys the jig but also leaves an immutable record. | ||
| + | == Transaction == | ||
| + | <div>A transaction in Run is an atomic update to jigs or code.</div> | ||
| + | <div> | ||
| + | Inputs => Computation => Outputs</div> | ||
| + | <div><br></div> | ||
| + | <div>Sample code for a transaction:</div> | ||
| + | <div><br></div> | ||
| + | <div>class Dragon extends Jig { }</div> | ||
| + | <div><br></div> | ||
| + | <div>const dragon = new Dragon()</div> | ||
| + | <div><br></div> | ||
| + | <div>Inputs are the jigs and code which will be updated. Computation is stored as executable statements in an op_return. The Run Virtual Machine executes these statements and produces outputs which are the jigs and code updated or created fresh. The data for these jigs are not stored in Bitcoin outputs, but instead are stored in an off-chain cache and able to be recomputed by others from the blockchain data. In this way Run transactions are kept small. There may also be payment inputs and outputs too that are not used by Run but part of the transaction. Here is the transaction format for the example to the right:</div> | ||
| + | <div> </div> | ||
| + | <div> | ||
| + | {| class="wikitable" style="border-collapse: collapse; width: 100%;" | ||
| + | |- | ||
| + | | style="width: 30.1087%;" | '''Inputs''' | ||
| + | | style="width: 69.8913%;" | '''Outputs''' | ||
| + | |- | ||
| + | | style="width: 30.1087%;" | 1. payment | ||
| + | | style="width: 69.8913%;" | 1. op_return: RUN metadata | ||
| + | |- | ||
| + | | style="width: 30.1087%;" | | ||
| + | <br> | ||
| + | | style="width: 69.8913%;" | 2. p2pkh: Dragon Class | ||
| + | |- | ||
| + | | style="width: 30.1087%;" | | ||
| + | <br> | ||
| + | | style="width: 69.8913%;" | 3. p2pkh: dragon jig instance | ||
| + | |- | ||
| + | | style="width: 30.1087%;" | | ||
| + | <br> | ||
| + | | style="width: 69.8913%;" | 4. change output for payment | ||
| + | |} | ||
| + | </div> | ||
| + | <div> </div> | ||
| + | <div><div>The op_return data is made up of both push data and a JSON payload. It has the following structure:</div> | ||
| + | <div> | ||
| + | [op_false] [op_return] 'run' <version> '<app-id>' '<json-payload>'</div> | ||
| + | <div><br></div> | ||
| + | <div>Each data field starts with an op_push specifying its length.</div> | ||
| + | <div>The protocol version is currently 0x05.</div> | ||
| + | <div>The app-id field enables applications to identify their Run transactions.</div> | ||
| + | <div>Strings are UTF-8 encoded.</div> | ||
| + | <div>[op_false] [op_return] is the standard prefix for metadata on Bitcoin SV since the Quasar hard fork.</div> | ||
| + | <div>You can easily identify Run transactions and its outputs using the op_return metadata.</div> | ||
| + | <div><br></div> | ||
| + | <div>Inspecting RUN metadata</div> | ||
| + | <div><br></div> | ||
| + | <div>const rawtx = await run.blockchain.fetch(txid)</div> | ||
| + | <div>const metadata = Run.util.metadata(rawtx)</div> | ||
| + | <div>console.log(metadata)</div></div> | ||
| + | <div> </div> | ||
| + | |||
| + | == JSON Payload == | ||
| + | <div>The JSON payload stores Run-specific metadata. To the right is a JSON payload for the example above. Its fields are:</div> | ||
| + | <div> | ||
| + | {| class="wikitable" style="border-collapse: collapse; width: 100%; height: 159px;" | ||
| + | |- style="background-color: #ced4d9; height: 23px;" | ||
| + | ! style="width: 25.3261%; height: 23px;" | '''Name''' | ||
| + | ! style="width: 74.6739%; height: 23px;" | '''Description''' | ||
| + | |- style="height: 21px;" | ||
| + | | style="width: 25.3261%; height: 21px; text-align: center;" | in | ||
| + | | style="width: 74.6739%; height: 21px;" | Number of jig and code inputs | ||
| + | |- style="height: 23px;" | ||
| + | | style="width: 25.3261%; height: 23px; text-align: center;" | ref | ||
| + | | style="width: 74.6739%; height: 23px;" | Array of references to jigs and code used by not spent | ||
| + | |- style="height: 23px;" | ||
| + | | style="width: 25.3261%; height: 23px; text-align: center;" | out | ||
| + | | style="width: 74.6739%; height: 23px;" | State hashes of jigs and code in transaction outputs | ||
| + | |- style="height: 23px;" | ||
| + | | style="width: 25.3261%; height: 23px; text-align: center;" | del | ||
| + | | style="width: 74.6739%; height: 23px;" | State hashes of jigs and code deleted | ||
| + | |- style="height: 23px;" | ||
| + | | style="width: 25.3261%; height: 23px; text-align: center;" | cre | ||
| + | | style="width: 74.6739%;" | New owners of jigs and code created | ||
| + | |- style="height: 23px;" | ||
| + | | style="width: 25.3261%; height: 23px; text-align: center;" | exec | ||
| + | | style="width: 74.6739%; height: 23px;" | Statements to execute on the jigs | ||
| + | |} | ||
| + | </div> | ||
| + | <div>The exec field in particular contains the statements for Run to execute. There are 4 opcodes supported by the RUN protocol in 0.6:</div> | ||
| + | <div> | ||
| + | {| class="wikitable" style="border-collapse: collapse; width: 100%; height: 115px;" | ||
| + | |- style="background-color: #ced4d9; height: 23px;" | ||
| + | ! style="width: 23.2609%; height: 23px;" | '''Opcode''' | ||
| + | ! style="width: 28.4782%; height: 23px;" | '''Description''' | ||
| + | ! style="width: 48.2609%; height: 23px;" | '''Data Format''' | ||
| + | |- style="height: 23px;" | ||
| + | | style="width: 23.2609%; height: 23px; text-align: center;" | DEPLOY | ||
| + | | style="width: 28.4782%; height: 23px;" | Upload new code | ||
| + | | style="width: 48.2609%; height: 23px;" | [<src1>, <props1>, <src2>, <props2>, ...] | ||
| + | |- style="height: 23px;" | ||
| + | | style="width: 23.2609%; height: 23px; text-align: center;" | NEW | ||
| + | | style="width: 28.4782%; height: 23px;" | Instantiate a jig | ||
| + | | style="width: 48.2609%; height: 23px;" | [<jig class>, <args>] | ||
| + | |- style="height: 23px;" | ||
| + | | style="width: 23.2609%; height: 23px; text-align: center;" | CALL | ||
| + | | style="width: 28.4782%; height: 23px;" | Call a method on a jig | ||
| + | | style="width: 48.2609%; height: 23px;" | [<jig>, <method>, <args>] | ||
| + | |- style="height: 23px;" | ||
| + | | style="width: 23.2609%; height: 23px; text-align: center;" | UPGRADE | ||
| + | | style="width: 28.4782%; height: 23px;" | Replace code with new code | ||
| + | | style="width: 48.2609%; height: 23px;" | [<code>, <src>, <props>] | ||
| + | |} | ||
| + | </div> | ||
| + | <div><div>The state hashes used in the out and del arrays are calculated by taking the sha-256 of the JSON serialization of the jigs. This state cache format will also be documented soon. Finally, the Run VM provides certain native classes, like Jig and Code, that are built-in to its virtual machine. Eventually this virtual machine will be stored on-chain too ensuring total trustlessness.</div> | ||
| + | <div><br></div> | ||
| + | <div>The protocol will be documented more in a coming spec. Reach out for any questions!</div></div> | ||
| + | <div> </div> | ||
| + | <div>Sample JSON payload:</div> | ||
| + | <div><br></div> | ||
| + | <div>{</div> | ||
| + | <div> "in": 0,</div> | ||
| + | <div> "ref": [</div> | ||
| + | <div> "native://Jig"</div> | ||
| + | <div> ],</div> | ||
| + | <div> "out": [</div> | ||
| + | <div> "e494cd3d0c33615620c22f44cddf85f2bf613fd608dbfc53822664581205d198",</div> | ||
| + | <div> "9a99596f417e8925cb25f2acf99abe28f014aaad47ce93c427ee3afd3bcc5084"</div> | ||
| + | <div> ],</div> | ||
| + | <div> "del": [],</div> | ||
| + | <div> "cre": [</div> | ||
| + | <div> "mhhHzeLjRTD4cjuygJFjqmCHCFpDKGrp75",</div> | ||
| + | <div> "mhhHzeLjRTD4cjuygJFjqmCHCFpDKGrp75"</div> | ||
| + | <div> ],</div> | ||
| + | <div> "exec": [</div> | ||
| + | <div> {</div> | ||
| + | <div> "op": "DEPLOY",</div> | ||
| + | <div> "data": ["class Dragon extends Jig { }", { "deps": { "Jig": { "$jig": 0 } } }]</div> | ||
| + | <div> },</div> | ||
| + | <div> {</div> | ||
| + | <div> "op": "NEW",</div> | ||
| + | <div> "data": [{ "$jig": 1 }, []]</div> | ||
| + | <div> }</div> | ||
| + | <div> ]</div> | ||
| + | <div>}</div> | ||
| + | |||
| + | == Serialization == | ||
| + | <div>Every jig, every argument to a method, and every static property of a class, must be serialized so that it can be restored later. Run uses a custom serialization format that is similar to JSON. The following data types are supported:</div><div><br></div><div>Numbers (IEEE-754)</div><div>Strings (UTF-8)</div><div>Booleans</div><div>Objects (Basic and Sidekicks)</div><div>Null and Undefined</div><div>Arrays</div><div>Uint8Arrays</div><div>Maps</div><div>Sets</div><div>Jigs</div><div>Code</div><div>Berries</div><div>All JavaScript IEEE 754 numbers types are serializable, including Infinity, NaN, and -0. Properties may be safely set on Sets, Maps, and Arrays, including any of the above types. Circular references are OK.</div><div><br></div><div>Symbols are not however serializable and will not be supported. Other JavaScript objects that are not currently supported include Date, WeakMap, Promise, Error, Float32Array, and BigInt.</div><div><br></div><div>Sidekick objects are JavaScript objects whose constructor is a sidekick class. Whereas jigs have blockchain locations and owners, and Run enforces that their state progresses from their method calls, sidekick objects are much simpler. They are stored by-value in their current state. A lock instance is an example of a sidekick object. In effect, they are data blobs with methods from on-chain code.</div><div><br></div><div>Pass a sidekick object in by value</div><div><br></div><div>class Person {</div><div> constructor(name, creationDate, profilePicture) {</div><div> this.name = name</div><div> this.creationDate = creationDate</div><div> this.profilePicture = profilePicture</div><div> }</div><div><br></div><div> valid() { ... }</div><div>}</div><div><br></div><div>class SocialGroup extends Jig {</div><div> constructor() { this.members = [] }</div><div><br></div><div> add(person) {</div><div> expect(person).toBeInstanceOf(Person)</div><div> expect(person.valid()).toBe(true)</div><div><br></div><div> this.members.push(person)</div><div> }</div><div>}</div><div><br></div><div>SocialGroup.deps = { Person, expect }</div><div><br></div><div>const group = new SocialGroup()</div><div><br></div><div>group.add(new Person('Li', new Date(), null))</div> | ||
| + | == Sandboxing == | ||
| + | All Code is sandboxed so that it does not have access to your application code, including your private keys! This provides security and also determinism when replaying a jig's history because a jig should evaluate the same in every environment. Run uses Agoric SES, the gold standard in secure JavaScript evalution, combined with the vm library in node and hidden iframes in the browser, to perform this sandboxing. Despite this, it is recommended you avoid running untrusted code. | ||
| + | == Safety Checks == | ||
| + | Run also protects you from performing updates on your jigs that will not be valid by others. For example, Run will throw an error if you try to change a property on a jig directly rather than call a method, or if you attempt to set a function as a property on a jig. Only top-level method calls may change a jig's state which is also enforced by Run. In addition, every Run transaction is pre-verified before it is published on your local machine. | ||
| + | == Ownership Rules == | ||
| + | <div>Jigs are special objects that have ownership rules which Run enforces. These include:</div><div><br></div><div>Ownership grants the right to change the jig’s state through an action.</div><div>Ownership grants the right to create new jigs from the jig, where those new jigs have the same owner as the creator jig.</div><div>Ownership grants the right to enact actions on other jigs from the jig that change the states of those other jigs, as long as the owners of those changed jigs approve.</div><div>Likewise, without ownership, the above actions cannot be performed. Proving ownership requires spending a Bitcoin output, so when ownership changes on a jig, further updates to that jig must occur in a new transaction. There is also a fourth rule of ownership that is a right granted to all jigs:</div><div><br></div><div>A jig may reference or read the state of another jig with or without its owner’s approval.</div> | ||
| + | == Privacy == | ||
| + | All jigs and jig code are stored on-chain and are open for everyone to read. This enables anyone to reconstruct the state of any jig. Privacy is achieved similar to Bitcoin UTXOs. For maximum privacy, public keys should not be re-used. In the future, we will introduce private jigs that are visible only to the current owners, but by their nature, they will not work as well with explorers, analytics and other services. | ||
| + | == Backwards Compatibility == | ||
| + | Starting in Run 0.6, which uses protocol 0x05, all jigs will be backwards-compatible. This means jigs you launch today will always be supported into the future by the Run SDK. This is our promise. To keep this promise, every jig is connected to its protocol version, so as Run is updated, older jigs can be kept operational with their original behavior. In addition, we run tests against on-chain jigs with every update to ensure that your jigs continue to work.</div> | ||
| + | <div>[[Category:Documentation]]</div> | ||
Latest revision as of 00:40, 29 April 2023
Contents
Overview
A jig is a JavaScript object that Run syncs with the blockchain. All of its code and method calls are stored on-chain in op_return metadata. Run can reconstruct the state of jigs by loading the code and replaying every method call, but usually intermediate states are cached by indexers. Most jigs are paired with a Bitcoin output so that only the owner of that output can make changes to the jig. All updates taken together form a transaction chain that enables consensus through user verification. This design is similar to other Layer-2 UTXO-based token systems because miners don't verify the JavaScript code. If anyone publishes an incorrect update, it not only destroys the jig but also leaves an immutable record.
Transaction
| Inputs | Outputs |
| 1. payment | 1. op_return: RUN metadata |
|
|
2. p2pkh: Dragon Class |
|
|
3. p2pkh: dragon jig instance |
|
|
4. change output for payment |
JSON Payload
| Name | Description |
|---|---|
| in | Number of jig and code inputs |
| ref | Array of references to jigs and code used by not spent |
| out | State hashes of jigs and code in transaction outputs |
| del | State hashes of jigs and code deleted |
| cre | New owners of jigs and code created |
| exec | Statements to execute on the jigs |
| Opcode | Description | Data Format |
|---|---|---|
| DEPLOY | Upload new code | [<src1>, <props1>, <src2>, <props2>, ...] |
| NEW | Instantiate a jig | [<jig class>, <args>] |
| CALL | Call a method on a jig | [<jig>, <method>, <args>] |
| UPGRADE | Replace code with new code | [<code>, <src>, <props>] |
Serialization
Sandboxing
All Code is sandboxed so that it does not have access to your application code, including your private keys! This provides security and also determinism when replaying a jig's history because a jig should evaluate the same in every environment. Run uses Agoric SES, the gold standard in secure JavaScript evalution, combined with the vm library in node and hidden iframes in the browser, to perform this sandboxing. Despite this, it is recommended you avoid running untrusted code.
Safety Checks
Run also protects you from performing updates on your jigs that will not be valid by others. For example, Run will throw an error if you try to change a property on a jig directly rather than call a method, or if you attempt to set a function as a property on a jig. Only top-level method calls may change a jig's state which is also enforced by Run. In addition, every Run transaction is pre-verified before it is published on your local machine.
Ownership Rules
Privacy
All jigs and jig code are stored on-chain and are open for everyone to read. This enables anyone to reconstruct the state of any jig. Privacy is achieved similar to Bitcoin UTXOs. For maximum privacy, public keys should not be re-used. In the future, we will introduce private jigs that are visible only to the current owners, but by their nature, they will not work as well with explorers, analytics and other services.