Skip to content

Commit

Permalink
Merge branch 'development'
Browse files Browse the repository at this point in the history
  • Loading branch information
cmdruid committed May 22, 2024
2 parents 9ab422b + 013358d commit 3a86d3d
Show file tree
Hide file tree
Showing 201 changed files with 3,774 additions and 4,049 deletions.
94 changes: 12 additions & 82 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ Each contract specifies a "script engine" or interpreter to use when evaluating
When the contract activates, a virtual machine is created using the specified engine. A hash-chain is also created, starting with the machine's identifier (vmid).

```ts
vm_state: {
vmdata: {
commits : [],
error : null,
head : 'b70704c41e27d5f35a11ae7c6e5976501aa1380195714007197d7f47934dcf69',
Expand All @@ -191,7 +191,7 @@ vm_state: {
}
```

Members of the contract can interact with this machine by submitting a signed statement, called a [witness](data/witness.md#witnessdata). These witness statements provide instructions to the virtual machine and execute programs.
Members of the contract can interact with this machine by submitting a signed statement, called a [witness](data/witness.md#witness-data). These witness statements provide instructions to the virtual machine and execute programs.

Each statement calls upon a `method`, an `action` to perform on success, and a target spending `path` in the contract.

Expand Down Expand Up @@ -237,8 +237,6 @@ vm_state: {
}
```

It

### Settlement

Once the machine has settled on a final outcome, the escrow agent will close the contract. If the machine specifies a spending path, the escrow agent will co-sign the relevant transaction and broadcast it to the Bitcoin network.
Expand Down Expand Up @@ -354,6 +352,8 @@ The current chains available are `mutiny`, `signet`, and `testnet`. The default

You can read more info about the demo [here](demo/README.md).

---

## Development / Testing

To get started, make sure you are running `v19+` of node, then install the project dependencies using your node manager of choice:
Expand All @@ -363,94 +363,22 @@ node --version # should be v19+
npm install # install dependencies
```

This project uses the following scripts:

```md
build : Compiles the contents of `src` folder to `dist`.
demo <chain> : Runs the protocol demo for the provided chain.
load <script> : Load and execute a `.ts` script at the provided path.
release : Builds and tests the current source for release.
scratch : Executes the `test/scratch.ts` file.
test : Runs the current test suite in `test/tape.ts`.
```

### Running the Demo

The main demo is located in the [/demo](demo) directory, and serves as a great resource for how to use the client library.

You can choose to run the protocol demo on the `mutiny`, `signet`, or `testnet` blockchain:

```bash
## Run the demo on the mutiny chain.
npm run demo mutiny
```

No wallet or software required[*]. Simply follow the interactive prompts, and enjoy the protocol in action.

> The mutiny chain is the fastest of the three demos, with 30 second blocks.
> [*] Testnet faucet is currently broke. You may need your own testnet coins.
### Running in Replit

There is a replit clone of this repo that you can run in the browser:

[https://replit.com/escrow-core](https://replit.com/@cscottdev/escrow-core)

Clicking `Run` at the top of the replit should run the demo.

Feel free to fork the replit and try out the developer tools!

### Using the Client API Demos

There is a suite of client API examples located in the [/demo/api](demo/api) directory.

Feel free to use `npm run load` to execute any of the example scripts:

```bash
npm run load demo/api/contract/read.ts
```
Check out the [Development](./docs/development.md) section for documentation and guides on how to use the test suite.

You can also specify a chain to use at the end of the command:

```bash
npm run load demo/api/deposit/list.ts mutiny
```

If you run into any errors when using the demos, please consider filing an issue ticket!

### Using the CVM Evaluation Tool

The CVM [eval](demo/vm/eval.ts) tool allows you to quickly evaluate a set of proposal terms and witness statements using a dummy virtual machine.

The tool uses an easy to read [JSON file](demo/vm/vector.json) to load the data. This file can be re-written to demonstrate any contract scenario you wish.

```
npm run demo:vm
```

The tool and JSON file are located in the [/demo/vm](demo/vm) directory.

### Using the Test Suite

The test suite is located in [test/src](test/src), and controlled by the [test/tape.ts](test/tape.ts) file. Feel free to add/remove test packages from the main test method.

Some tests come with a verbose output, which you can enable with the `VERBOSE=true` flag.

Example of running the current test suite in verbose mode:

```bash
VERBOSE=true npm run test
```
---

## Questions / Issues

Feel free to post questions or comments on the issue board. All feedback is welcome.

---

## Contribution

Help wanted. All contributions are welcome!

---

## Resources

Nearly the entire code-base has been built from scratch, with only one hard third-party dependency and a couple soft dependencies.
Expand Down Expand Up @@ -509,6 +437,8 @@ Reference implementation of the new hybrid signing device / wallet we are buildi

https://github.com/cmdruid/signer

---

# Footnote

My inspiration for this project comes from the Bitcoin space, and the incredibly talented people that contribute. I will be forever grateful for their knowledge, kindness and spirit.
Expand Down
11 changes: 4 additions & 7 deletions demo/00_demo_config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { Network } from '@scrow/sdk'
import { get_server_config } from '@scrow/test'
import { ChainNetwork, get_server_config } from '@scrow/sdk'

import DefaultEngine from '@/vm/index.js'
import DefaultPolicy from '@/client/config/policy.js'

const faucets = {
Expand All @@ -11,7 +9,7 @@ const faucets = {
testnet : 'https://bitcoinfaucet.uo1.net'
}

const returns = {
const return_addresses = {
mutiny : 'tb1phdk3ag8vmjdmlx0ugwvmleh2qf22k28kp8mw7t7su6ucqmmvuauqvav4s3',
regtest : 'bcrt1pdcfvw8ulj6qtr8mj8gjqgl76ff8l8q2fjmvect8m0p22ghl2dsgqzjk3hd',
signet : 'tb1q5tsjcyz7xmet07yxtumakt739y53hcttmntajq',
Expand All @@ -28,17 +26,16 @@ const poll_rates = {
const feerate = 2
const locktime = 172800
const network = process.env.NETWORK ?? 'mutiny'
const client = get_server_config(network as Network)
const client = get_server_config(network as ChainNetwork)

export const config = {
client,
feerate,
locktime,
network,
engine : DefaultEngine,
faucet : faucets[network as keyof typeof faucets],
members : [ 'alice', 'bob', 'carol' ],
policy : DefaultPolicy,
poll : poll_rates[network as keyof typeof poll_rates],
return_addr : returns[network as keyof typeof returns]
return_addr : return_addresses[network as keyof typeof return_addresses]
}
11 changes: 9 additions & 2 deletions demo/01_create_client.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { EscrowClient } from '@scrow/sdk'
import { print_banner } from '@scrow/test'

import { config } from './00_demo_config.js'

const DEMO_MODE = process.env.VERBOSE === 'true'

/**
* Define our API client.
* Create a new API client using a ClientConfig object.
*/

export const client = new EscrowClient(config.client)

if (DEMO_MODE) {
print_banner('client config')
console.dir(config.client)
}
22 changes: 12 additions & 10 deletions demo/02_create_signer.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { EscrowSigner } from '@scrow/sdk/client'
import { config } from './00_demo_config.js'
import { print_banner } from '@scrow/test'

import { config } from './00_demo_config.js'

const DEMO_MODE = process.env.VERBOSE === 'true'

/**
* Utility method for creating a list of
* signers from a list of strings.
* Create a list of signing devices to use.
*/
function create_signer (alias : string) {
// Return an escrow signer.
export const signers = config.members.map(alias => {
return EscrowSigner.import(config.client).from_phrase(alias)
}
})

/**
* Define our list of signers.
*/
export const signers = config.members.map(e => create_signer(e))
if (DEMO_MODE) {
print_banner('signing members')
console.log(config.members)
}
8 changes: 5 additions & 3 deletions demo/03_create_proposal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import { config } from './00_demo_config.js'
import { signers } from './02_create_signer.js'

/**
* Define an (optional) moderator for our proposal.
* We can specify one of our signers to be a moderator.
*
* Moderators have a limited ability to manage or cancel
* a contract during the funding stage.
*/

export const moderator = signers[2]

/**
Expand All @@ -22,7 +24,7 @@ export const proposal : ProposalTemplate = {
moderator : moderator.pubkey,
network : config.network,
schedule : [[ 7200, 'close|resolve', 'payout|refund' ]],
value : 10000,
value : 10000
}

/**
Expand Down
36 changes: 29 additions & 7 deletions demo/04_finish_proposal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,52 @@ import { proposal, roles } from './03_create_proposal.js'

const DEMO_MODE = process.env.VERBOSE === 'true'

// Unpack our list of signers.
/**
* Unpack our list of signers.
*/
const [ a_signer, b_signer, c_signer ] = signers

// Define our negotiation session.
let draft = DraftUtil.create({ proposal, roles }),
seats = draft.roles.map(e => e.id)
/**
* Create a DraftSession object. This data object is
* useful for collaboration between signing devices.
*/
let draft = DraftUtil.create({ proposal, roles })

/**
* For each role in the proposal, we are going to request
* a member's signing device to join the proposal as that
* role, adding payment information as needed.
*/
const seats = draft.roles.map(e => e.id)

// For each member, add their info to the proposal.
draft = a_signer.draft.join(seats[0], draft)
draft = b_signer.draft.join(seats[1], draft)
draft = c_signer.draft.join(seats[2], draft)

// For each member, collect an endorsement signature.
/**
* For each signer, we are going to collect a signature
* endorsement. This step is optional, but we can use it
* to signal readiness for a proposal to be submitted.
*/
signers.forEach(mbr => {
draft = mbr.draft.endorse(draft)
})

/**
* Verify the proposal is complete, all positions are
* filled, and endorsements are valid.
*/
DraftUtil.verify(draft)

/**
* Create a publish request. This is a request body for
* publishing a contract on the escrow server.
*/
const publish_req = DraftUtil.publish(draft)

if (DEMO_MODE) {
print_banner('final draft')
console.dir(draft, { depth : null })
}

export { publish_req }
export { publish_req }
28 changes: 20 additions & 8 deletions demo/05_create_contract.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,35 @@
import CVM from '@scrow/sdk/cvm'
import { print_banner } from '@scrow/test'
import { config } from './00_demo_config.js'

import { client } from './01_create_client.js'
import { publish_req } from './04_finish_proposal.js'

const DEMO_MODE = process.env.VERBOSE === 'true'

// Unpack the default script engine and server policy.
const { engine, policy } = config
// Deliver proposal and endorsements to server.
const res = await client.contract.create(engine, policy, publish_req)
// Check if response is valid.
/**
* We will need to pass in a reference to the scripting engine
* defined in the proposal, so that it can verify the terms set
* for each program.
*/
const engine = CVM

/**
* Request to create a new contract on the escrow server.
*/
const res = await client.contract.create(publish_req, engine)
// Check the server response is valid.
if (!res.ok) throw new Error(res.error)

/**
* Define our published contract.
* The server will respond with a new contract. This contract
* will be published under a contract id (cid), which can be
* referenced for reading and funding.
*/
export const new_contract = res.data.contract
const new_contract = res.data.contract

if (DEMO_MODE) {
print_banner('new contract')
console.dir(new_contract, { depth : null })
}

export { new_contract }
Loading

0 comments on commit 3a86d3d

Please sign in to comment.