Difference between revisions of "How It Works"
| Line 1: | Line 1: | ||
<div> | <div> | ||
| + | |||
== Overview == | == 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. | 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. | ||
| Line 5: | Line 6: | ||
<div>A transaction in Run is an atomic update to jigs or code.</div> | <div>A transaction in Run is an atomic update to jigs or code.</div> | ||
<div> | <div> | ||
| − | Inputs => Computation => Outputs | + | Inputs => Computation => Outputs</div> |
| − | </div> | ||
<div><br></div> | <div><br></div> | ||
<div>Sample code for a transaction:</div> | <div>Sample code for a transaction:</div> | ||
| Line 17: | Line 17: | ||
<div> </div> | <div> </div> | ||
<div> | <div> | ||
| − | {| class="wikitable" style="border-collapse: collapse; width: 100%;" | + | |
| − | |- | + | {| class="wikitable" style="border-collapse: collapse; width: 100%;" |
| + | |- | ||
| style="width: 30.1087%;" | '''Inputs''' | | style="width: 30.1087%;" | '''Inputs''' | ||
| style="width: 69.8913%;" | '''Outputs''' | | style="width: 69.8913%;" | '''Outputs''' | ||
| − | |- | + | |- |
| style="width: 30.1087%;" | 1. payment | | style="width: 30.1087%;" | 1. payment | ||
| style="width: 69.8913%;" | 1. op_return: RUN metadata | | style="width: 69.8913%;" | 1. op_return: RUN metadata | ||
| − | |- | + | |- |
| style="width: 30.1087%;" | | | style="width: 30.1087%;" | | ||
| + | <br> | ||
| style="width: 69.8913%;" | 2. p2pkh: Dragon Class | | style="width: 69.8913%;" | 2. p2pkh: Dragon Class | ||
| − | |- | + | |- |
| style="width: 30.1087%;" | | | style="width: 30.1087%;" | | ||
| + | <br> | ||
| style="width: 69.8913%;" | 3. p2pkh: dragon jig instance | | style="width: 69.8913%;" | 3. p2pkh: dragon jig instance | ||
| − | |- | + | |- |
| style="width: 30.1087%;" | | | style="width: 30.1087%;" | | ||
| + | <br> | ||
| style="width: 69.8913%;" | 4. change output for payment | | style="width: 69.8913%;" | 4. change output for payment | ||
|} | |} | ||
| Line 38: | Line 42: | ||
<div><div>The op_return data is made up of both push data and a JSON payload. It has the following structure:</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> | <div> | ||
| − | [op_false] [op_return] 'run' <version> '<app-id>' '<json-payload>' | + | [op_false] [op_return] 'run' <version> '<app-id>' '<json-payload>'</div> |
| − | </div> | ||
<div><br></div> | <div><br></div> | ||
<div>Each data field starts with an op_push specifying its length.</div> | <div>Each data field starts with an op_push specifying its length.</div> | ||
| Line 56: | Line 59: | ||
== JSON Payload == | == 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> | + | <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;" | {| class="wikitable" style="border-collapse: collapse; width: 100%; height: 159px;" | ||
| − | |- style="background-color: rgb(206, 212, 217); height: 23px;" | + | |- style="background-color: rgb(206, 212, 217); height: 23px;" |
! style="width: 25.3261%; height: 23px;" | '''Name''' | ! style="width: 25.3261%; height: 23px;" | '''Name''' | ||
! style="width: 74.6739%; height: 23px;" | '''Description''' | ! style="width: 74.6739%; height: 23px;" | '''Description''' | ||
| Line 80: | Line 85: | ||
| style="width: 74.6739%; height: 23px;" | Statements to execute on the jigs | | 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> | + | </div> |
| − | {| class="wikitable" style="border-collapse: collapse; width: 100%; height: 115px;" | + | <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> |
| − | |- style="background-color: rgb(206, 212, 217); height: 23px;" | + | <div> |
| + | |||
| + | {| class="wikitable" style="border-collapse: collapse; width: 100%; height: 115px;" | ||
| + | |- style="background-color: rgb(206, 212, 217); height: 23px;" | ||
! style="width: 23.2609%; height: 23px;" | '''Opcode''' | ! style="width: 23.2609%; height: 23px;" | '''Opcode''' | ||
! style="width: 28.4782%; height: 23px;" | '''Description''' | ! style="width: 28.4782%; height: 23px;" | '''Description''' | ||
| Line 93: | Line 101: | ||
| style="width: 23.2609%; height: 23px; text-align: center;" | NEW | | style="width: 23.2609%; height: 23px; text-align: center;" | NEW | ||
| style="width: 28.4782%; height: 23px;" | Instantiate a jig | | style="width: 28.4782%; height: 23px;" | Instantiate a jig | ||
| − | | style="width: 48.2609%; height: 23px;" | | + | | style="width: 48.2609%; height: 23px;" | [<jig class>, <args>] |
|- style="height: 23px;" | |- style="height: 23px;" | ||
| style="width: 23.2609%; height: 23px; text-align: center;" | CALL | | style="width: 23.2609%; height: 23px; text-align: center;" | CALL | ||
| Line 103: | Line 111: | ||
| style="width: 48.2609%; height: 23px;" | [<code>, <src>, <props>] | | 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> | + | </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 == | == Serialization == | ||
== Sandboxing == | == Sandboxing == | ||
Revision as of 00:38, 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
A transaction in Run is an atomic update to jigs or code.
Inputs => Computation => Outputs
Sample code for a transaction:
class Dragon extends Jig { }
const dragon = new Dragon()
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:
| Inputs | Outputs |
| 1. payment | 1. op_return: RUN metadata |
|
|
2. p2pkh: Dragon Class |
|
|
3. p2pkh: dragon jig instance |
|
|
4. change output for payment |
The op_return data is made up of both push data and a JSON payload. It has the following structure:
[op_false] [op_return] 'run' <version> '<app-id>' '<json-payload>'
Each data field starts with an op_push specifying its length.
The protocol version is currently 0x05.
The app-id field enables applications to identify their Run transactions.
Strings are UTF-8 encoded.
[op_false] [op_return] is the standard prefix for metadata on Bitcoin SV since the Quasar hard fork.
You can easily identify Run transactions and its outputs using the op_return metadata.
Inspecting RUN metadata
const rawtx = await run.blockchain.fetch(txid)
const metadata = Run.util.metadata(rawtx)
console.log(metadata)
JSON Payload
The JSON payload stores Run-specific metadata. To the right is a JSON payload for the example above. Its fields are:
| 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 |
The exec field in particular contains the statements for Run to execute. There are 4 opcodes supported by the RUN protocol in 0.6:
| 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>] |
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.
The protocol will be documented more in a coming spec. Reach out for any questions!
Sample JSON payload:
{
"in": 0,
"ref": [
"native://Jig"
],
"out": [
"e494cd3d0c33615620c22f44cddf85f2bf613fd608dbfc53822664581205d198",
"9a99596f417e8925cb25f2acf99abe28f014aaad47ce93c427ee3afd3bcc5084"
],
"del": [],
"cre": [
"mhhHzeLjRTD4cjuygJFjqmCHCFpDKGrp75",
"mhhHzeLjRTD4cjuygJFjqmCHCFpDKGrp75"
],
"exec": [
{
"op": "DEPLOY",
"data": ["class Dragon extends Jig { }", { "deps": { "Jig": { "$jig": 0 } } }]
},
{
"op": "NEW",
"data": [{ "$jig": 1 }, []]
}
]
}