Browse Source

Merge pull request #21 from Bucko13/funding-guide

Crowdfunding guide
beginners-guide
Buck Perley 7 years ago
committed by GitHub
parent
commit
068165d210
  1. 499
      guides-markdown/crowdfund-tx.md
  2. 35
      guides-markdown/multisig-tx.md
  3. 26
      guides.html
  4. 811
      guides/crowdfund-tx.html
  5. 3
      guides/generate-address.html
  6. 3
      guides/install-linux.html
  7. 3
      guides/install-mac.html
  8. 3
      guides/install-windows.html
  9. 46
      guides/multisig-tx.html
  10. 5
      guides/op_return.html
  11. 3
      guides/scripting.html
  12. 2
      utils/createHTML.js

499
guides-markdown/crowdfund-tx.md

@ -0,0 +1,499 @@
# Create a Crowdfunding Transaction
```post-author
Buck Perley
```
```post-description
Learn how SIGHASH flags work in Bitcoin by building out a custom crowdfunding transaction that lets anyone add their own inputs to a transaction with a fixed output.
```
## SIGHASH Flags
In most Bitcoin transactions, when a transaction is signed, the entirety of the data in that transaction is committed to in that input's signature, with all outputs and inputs being included in the unlocking script. This, however, doesn't always have to be the case. The level of commitment is indicated by using `SIGHASH` flags. The most common flag is `SIGHASH_ALL` which has a value of 0x01 (you'll see this represented as a `01` at the end of DER-encoded signatures). To learn more about how the flags work and what other options are available, you should checkout [Chapter 6](https://github.com/bitcoinbook/bitcoinbook/blob/8d01749bcf45f69f36cf23606bbbf3f0bd540db3/ch06.asciidoc) of *Mastering Bitcoin* by Andreas Antonopolous. In that chapter, Andreas posits one novel use of a specialized flag, `ALL|ANYONECANPAY`, and in this guide we'll try and build out a couple of examples implementing this idea using bcoin.
## How it Works
The `ALL|ANYONECANPAY` flag indicates that a signature is committing all of the outputs and just one input. The suggested use case of this proposed in *Mastering Bitcoin* is a kickstarter-like crowdfunding application. Consider the situation where you have a fundraising goal, say 1BTC. You'd like multiple people to contribute to your goal and you want to prove to them that they won't have to pay *unless* you reach your goal (i.e. the transaction is invalid and won't be accepted by the network if attempted to be sent). This means you'd be committing to one output, the one that sends the funds to the charity or project you'd like to donate to, and only one input, your contribution. This allows multiple users to contribute to the same transaction and that transaction won't be valid until it's fully funded.
Here's how it's explained in *Mastering Bitcoin*:
> ALL|ANYONECANPAY
This construction can be used to make a "crowdfunding”-style transaction. Someone attempting to raise funds can construct a transaction with a single output. The single output pays the "goal" amount to the fundraiser. Such a transaction is obviously not valid, as it has no inputs. However, others can now amend it by adding an input of their own, as a donation. They sign their own input with ALL|ANYONECANPAY. Unless enough inputs are gathered to reach the value of the output, the transaction is invalid. Each donation is a "pledge," which cannot be collected by the fundraiser until the entire goal amount is raised.
## The Code
We'll walk through the steps of creating the transaction first without any wallet database or node running. Then we'll do the same thing using bcoin's walletdb to manage the keys to see how it would work in a more realistic application (skip to [Version 2](#version-2-using-the-bcoin-wallet-system)) further in the guide to check it out). At the end, we'll put out some ideas of how these can be built upon for a more robust, production ready application. (If this is something you'd be interested in building, [get in touch](http://bcoin.io/slack-signup.html)!). If you want to see the code, checkout the [repo on github](https://github.com/Bucko13/bitcoin-fundraise).
If you're not comfortable with key management, coin selection, and how transactions are constructed, checkout the tutorial on [working with transactions](https://github.com/bcoin-org/bcoin/blob/master/docs/Working-with-transactions.md) first.
### Version 1 - Manual Key Management
#### Step 1: Setup
Let's first start by importing the right tools, setting up some constants, and creating our keychains. (make sure you've installed the latest version of bcoin into your project with `npm install bcoin`).
Note that we're setting the fundingTarget and amountToFund as constants for simplicity, but they could be set based on user input or some other variable circumstances.
```javascript
'use strict';
const assert = require('assert');
const bcoin = require('bcoin');
const MTX = bcoin.mtx;
const Keyring = bcoin.keyring;
const Outpoint = bcoin.outpoint;
const Script = bcoin.script;
const Coin = bcoin.coin;
const policy = bcoin.protocol.policy
const fundingTarget = 100000000; // 1 BTC
const amountToFund = 50000000; // .5 BTC
const txRate = 10000; // 10000 satoshis/kb
```
Let's derive private hd key for fundee and two funders and create a "keyring" object for each (much of this is borrowed from the *Working with Transactions* guide).
A keyring object is basically a key manager that is also able to tell you info such as:
- your redeem script
- your scripthash
- your program hash
- your pubkey hash
- your scripthash program hash
```javascript
// Create an HD master keypair.
const master = bcoin.hd.generate();
const fundeeKey = master.derive(0);
const fundeeKeyring = new Keyring(fundeeKey.privateKey);
const fundeeAddress = fundeeKeyring.getAddress();
// Derive 2 more private hd keys and keyrings for funders
const funder1Key = master.derive(1);
const funder1Keyring = new Keyring(funder1Key.privateKey);
const funder2Key = master.derive(2);
const funder2Keyring = new Keyring(funder2Key.privateKey);
const funders = [funder1Keyring, funder2Keyring];
```
#### Step 2: Fund the Keyrings
This example is working in an isolated environment, so it won't work on the actual network (main, test, or otherwise), but we also don't have to earn or send ourselves coins or wait for confirmation times. That means that we can "spawn" coins for our funder wallets that they can use to spend on the crowdfunding platform.
Let's create some coinbase transactions to give our keyrings some coins that they can spend.
```javascript
// create some coinbase transactions to fund our wallets
const coins = {};
for(let i=0; i < funders.length; i++) {
const cb = new MTX();
// Add a typical coinbase input
cb.addInput({
prevout: new Outpoint(),
script: new Script()
});
cb.addOutput({
address: funders[i].getAddress(),
value: 500000000 // give the funder 5BTC
});
assert(cb.inputs[0].isCoinbase());
// Convert the coinbase output to a Coin
// object and add it to the available coins for that keyring.
// In reality you might get these coins from a wallet.
coins[i] = [Coin.fromTX(cb, 0, -1)];
}
```
The coins object you've created above should look something like this:
```json
{
"0":
[
{
"type": "pubkeyhash",
"version": 1,
"height": -1,
"value": "5.0",
"script": <Script: OP_DUP OP_HASH160 0x14 0x64cc4e55b2daec25431bd879ef39302a77c1c1ce OP_EQUALVERIFY OP_CHECKSIG>,
"coinbase": true,
"hash": "151e5551cdcec5fff06818fb78ac3d584361276e862b5700110ec8321869d650",
"index": 0,
"address": <Address: type=pubkeyhash version=-1 str=mphvcfcFneRZvyYsmzhy57cSDzFbGrWaRb>
}
],
"1": [...]
}
```
#### Step 4: Prepare your Coins
Above, we just funded our funder accounts with a single 5BTC outpoint. This means that the next transaction funded from these accounts can only use that one outpoint (or *coin*) as an input and send the remainder back as change. Remember, in Bitcoin the way you send funds is you fund a transaction with a full UTXO (in this case we only have one worth 5BTC available to our keychains) and then send the change back to yourself as an additional output. Since ALL|ANYONECANPAY transactions mean a fixed output, you can't add new change outputs without other signatures becoming invalid which means we need a coin available equal to the amount we want to contribute to the crowdfund.
So what we want to do is have each funder create a coin (UTXO) with the value of what they want to donate.
The first thing we need to do make this work is calculate what the input will be. In our examples we are assuming that the funders cover the fee. Since different keyrings can be using different transaction types of different sizes (p2sh, multisig, etc.), we need a utility to calculate how much the fee should be for that input and add that to the amount to fund with.
##### Utility functions
We'll need some utility functions to help us out. It's nice to split these out separate from our main operations since we'll actually be reusing some of the functionality.
Before we build out the tools to calculate fees and split coins, we'll need a utility for composing the inputs for txs that we'll use for our mock transactions in the fee calculator and later for templating our real transaction
```javascript
const addInput = function addInput(coin, inputIndex, mtx, keyring, hashType) {
const sampleCoin = coin instanceof Coin ? coin : Coin.fromJSON(coin);
if(!hashType) hashType = Script.hashType.ANYONECANPAY | Script.hashType.ALL;
mtx.addCoin(sampleCoin);
mtx.scriptInput(inputIndex, sampleCoin, keyring);
mtx.signInput(inputIndex, sampleCoin, keyring, hashType);
assert(mtx.isSigned(), 'Input was not signed properly');
}
```
Now let's build the utility for calculating the fee for a single input of unknown type or size
```javascript
const getFeeForInput = function getFeeForInput(coin, address, keyring, rate) {
const fundingTarget = 100000000; // 1 BTC (arbitrary for purposes of this function)
const testMTX = new MTX();
// we're not actually going to use this tx for anything other than calculate what fee should be
addInput(coin, 0, testMTX, keyring);
return testMTX.getMinFee(null, rate);
}
```
Our last utility is an asyncronous function to help us split the coinbases we created in the previous step (we use the `fund` method on the `MTX` primitive to do this, which is asynchronous).
```javascript
const splitCoinbase = async function splitCoinbase(funderKeyring, coin, targetAmount, txRate) {
// loop through each coinbase coin to split
let coins = [];
const mtx = new MTX();
assert(coin.value > targetAmount, 'coin value is not enough!');
// creating a transaction that will have an output equal to what we want to fund
mtx.addOutput({
address: funderKeyring.getAddress(),
value: targetAmount
});
// the fund method will automatically split
// the remaining funds to the change address
// Note that in a real application these splitting transactions will also
// have to be broadcast to the network
await mtx.fund([coin], {
rate: txRate,
// send change back to an address belonging to the funder
changeAddress: funderKeyring.getAddress()
}).then(() => {
// sign the mtx to finalize split
mtx.sign(funderKeyring);
assert(mtx.verify());
const tx = mtx.toTX();
assert(tx.verify(mtx.view));
const outputs = tx.outputs;
// get coins from tx
outputs.forEach((outputs, index) => {
coins.push(Coin.fromTX(tx, index, -1));
});
})
.catch(e => console.log('There was an error: ', e));
return coins;
};
```
Because of the async methods being used, in order to take advantage of the async/await structure, the rest of the code will be enclosed in an async function.
The first thing we'll do is split the coinbase coins we created earlier using the utility function we just built (we'll also have to calculate the fee and add it to the funding amount in order to get an output of the right value).
```javascript
const composeCrowdfund = async function composeCrowdfund(coins) {
const funderCoins = {};
// Loop through each coinbase
for (let index in coins) {
const coinbase = coins[index][0];
// estimate fee for each coin (assuming their split coins will use same tx type)
const estimatedFee = getFeeForInput(coinbase, fundeeAddress, funders[index], txRate);
const targetPlusFee = amountToFund + estimatedFee;
// split the coinbase with targetAmount plus estimated fee
const splitCoins = await Utils.splitCoinbase(funders[index], coinbase, targetPlusFee, txRate);
// add to funderCoins object with returned coins from splitCoinbase being value,
// and index being the key
funderCoins[index] = splitCoins;
}
// ... we'll keep filling out the rest of the code here
};
```
`funderCoins` should return x number of coin arrays, where X is the number of coinbases we created earlier (should be 2) with each array having a coin equal to the amount we want to donate.
For example...
```json
{
"0":
[
{
"type": "pubkeyhash",
"version": 1,
"height": -1,
"value": "0.5000157"
"script": <Script: OP_DUP OP_HASH160 0x14 0x62f725e83caf894aa6c3efd29ef28649fc448825 OP_EQUALVERIFY OP_CHECKSIG>,
"coinbase": false,
"hash": "774822d84bd5af02f1b3eacd6215e0a1bcf07cfb6675a000c8a01d2ea34f2a32",
"index": 0,
"address": <Address: type=pubkeyhash version=-1 str=mpYEb17KR7MVhuPZT1GsW3SywZx8ihYube>
},
...
],
"1": [...]
}
```
#### Step 6: Construct the Transaction
Now that we've got our tools and coins ready, we can start to build the transaction!
```javascript
const composeCrowdfund = async function composeCrowdfund(coins) {
//...
const fundMe = new MTX();
// add an output with the target funding amount
fundMe.addOutput({ value: fundingTarget, address: fundeeAddress });
// fund with first funder
let fundingCoin = funderCoins['0'][0];
addInput(fundingCoin, 0, fundMe, funder1Keyring);
// fund with second funder
fundingCoin = funderCoins['1'][0];
addInput(fundingCoin, 1, fundMe, funder2Keyring);
// We want to confirm that total value of inputs covers the funding goal
// NOTE: the difference goes to the miner in the form of fees
assert(fundMe.getInputValue() >= fundMe.outputs[0].value, 'Total inputs not enough to fund');
assert(fundMe.verify(), 'The mtx is malformed');
const tx = fundMe.toTX();
console.log('total input value = ', fundMe.getInputValue());
console.log('Fee getting sent to miners:', fundMe.getInputValue() - fundingTarget, 'satoshis');
assert(tx.verify(fundMe.view), 'there is a problem with your tx');
return tx;
};
composeCrowdfund(coins).then(myCrowdfundTx => console.log(myCrowdfundTx));
```
`composeCrowdfund` will now return a promise (thanks to async/await) that returns a fully templated transaction that can be transmitted to the network. It should have two inputs and one output with a value of 1. The inputs will have a value equal to the amount to fund plus the cost of the fee. You should also notice the `SIGHASH` flag 0x81 at the end of the input scripts which confirms they are `ALL|ANYONECANPAY` scripts.
### Version 2: Using the Bcoin Wallet System
Since trying to manage your own keys is pretty tedious, not to mention impractical especially if you want to let other people contribute to your campaign, let's use the bcoin wallet system to take care of that part of the process. For the this example, we're going to interact via the wallet client, but you could also do something similar within a bcoin node (using the wallet and walletdb directly) which would also be more secure.
Note that this is a little more tedious to test since you need to have funded wallets in order to actually fund your campaign. You can find a bitcoin testnet faucet to get some funds to play with or, as we will do in this example, create your own simnet or regtest network where you mine your own blocks to fund yourself.
#### Step 1: Setup Our Wallets
We'll skip the setup of constants import modules since we can use the same from the previous example. Since there are a lot of asynchronous operations here now that we're using the client, we'll also put this in an async function and will continue to build out the contents of the function throughout this guide. We'll also be using some of the same [utility functions that we created in the last example](#utility-functions).
```javascript
const network = 'regtest';
const composeWalletCrowdfund = async function composeWalletCrowdfund() {
const client = await new bcoin.http.Client({ network });
// Step 1: Setup our wallets and funding targets
const fundeeWallet = await new httpWallet({ id: 'fundee', network });
const fundeeAddress = await fundeeWallet.createAddress('default');
const funders = {
'funder1': await new httpWallet({ id: 'funder1', network }),
'funder2': await new httpWallet({ id: 'funder2', network })
};
//...
}
```
#### Step 2: Prepare Your Coins
We have the same issue to deal with here as in step 2 in the previous example: we need to have "exact change" coins available for funding. The process of splitting is a little different with the wallet system though so let's walk through this version.
Note that the way that we're retrieving the keyring information is pretty insecure as we are sending private keys unencrypted across the network, but we'll leave for the sake of the example. **DON'T USE THIS IN PRODUCTION**.
```javascript
const composeWalletCrowdfund = async function composeWalletCrowdfund() {
//...
const fundingCoins = {};
// go through each funding wallet to prepare coins
for(let id in funders) {
const funder = funders[id];
const coins = await funder.getCoins();
const funderInfo = await funder.getInfo();
// Before we do anything we need to get
// the fee that will be necessary for each funder's input.
const funderKey = await funder.getWIF(coins[0].address);
const funderKeyring = new bcoin.keyring.fromSecret(funderKey.privateKey);
const feeForInput = Utils.getFeeForInput(coins[0], fundeeAddress.address, funderKeyring, rate);
amountToFund += feeForInput;
// Next, go through available coins
// to find a coin equal to or greater than value to fund
// We didn't do this before because we knew what coins were available. But if we have one already in our wallets, then we can just use that!
let fundingCoin = {};
for(let coin of coins) {
if (coin.value === amountToFund) {
// if we already have a coin of the right value we can use that
fundingCoin = coin;
break;
}
}
if (!Object.keys(fundingCoin).length) {
// if we don't have a coin of the right amount to fund with
// we need to create one by sending the funder wallet
// a tx that includes an output of the right amount
// this is similar to what we did in the manual version
const receiveAddress = await funder.createAddress('default') // send it back to the funder
const tx = await funder.send({
rate,
outputs: [{
value: amountToFund,
address: receiveAddress.address
}]
});
// get index of ouput for fundingCoin
let coinIndex;
for (let i=0; i < tx.outputs.length; i++) {
if (tx.outputs[i].value === amountToFund) {
coinIndex = i;
break;
}
}
assert(tx.outputs[coinIndex].value === amountToFund, 'value of output at index not correct');
// first argument is for the account
// default is being used for all examples
fundingCoin = await funder.getCoin('default', tx.hash, coinIndex);
}
fundingCoins[funder.id] = fundingCoin;
}
}
```
We now should have an object available that has the information of the coins we will be using to fund our transaction with mapped to the name of each wallet (so we can retrieve the wallet information later). It should look something like this (note that the values are larger than our funding amount due to the fee):
```json
{
"funder1": {
"version": 1,
"height": -1,
"value": 50002370,
"script": "76a914127cb1a40212169c49fe22d13307b18af1fa07ad88ac",
"address": "SNykaBMuTyeUQkK8exZyymWNrnYX5vVPuY",
"coinbase": false,
"hash": "163068016a39e2d9c869bcdb8646dbca93e07824db39217b5c444e7c61d1a82c",
"index": 0
},
"funder2": {
"version": 1,
"height": -1,
"value": 50002370,
"script": "76a9146e08c73b355e690ba0b1198d578c4c6c52b3813688ac",
"address": "SXKossD65D7h62fhzGrntERBrPeXUfiC92",
"coinbase": false,
"hash": "11f3180c5069f2692f1ee1463257b21dc217441e792493c8f5ee230c35d97d96",
"index": 0
}
}
```
#### Step 3: Create our Crowdfund Tx
Now that we have our coins ready we can start to template the transaction!
Please note again that the way we are funding the transactions is by sending our private keys unencrypted across the network so don't use this in production.
```javascript
const composeWalletCrowdfund = async function composeWalletCrowdfund() {
//...
const fundMe = new MTX();
// Use the maxFee to calculate output value for transaction
fundMe.addOutput({value: fundingTarget, address: fundeeAddress.address });
// go through our coins and add each as an input in our transaction
let inputCounter = 0;
for(let funder in fundingCoins) {
const wallet = funders[funder];
const coinOptions = fundingCoins[funder];
const key = await wallet.getWIF(coinOptions.address);
const keyring = new bcoin.keyring.fromSecret(key.privateKey);
// this is the same utility as we used in our other example
addInput(coinOptions, inputCounter, fundMe, keyring);
assert(fundMe.isSigned(), 'Input has not been signed correctly');
inputCounter++;
}
// confirm that the transaction has been properly templated and signed
assert(
fundMe.inputs.length === Object.keys(funders).length,
'Number of inputs in MTX is incorrect'
);
assert(fundMe.verify(), 'MTX is malformed');
// make our transaction immutable so we can send it to th enetwork
const tx = fundMe.toTX();
assert(tx.verify(fundMe.view), 'TX is malformed. Fix before broadcasting');
// check the value of our inputs just to confirm what the fees are
console.log('Total value of inputs: ', fundMe.getInputValue() );
console.log('Fee to go to miners: ', fundMe.getInputValue() - fundingTarget);
// Finally, broadcast tx
try {
const broadcastStatus = await client.broadcast(tx);
return tx;
} catch (e) {
console.log('There was a problem: ', e);
}
}
composeWalletCrowdfund()
.then(myCrowdfundTx => console.log('Transaction broadcast: ', myCrowdfundTx))
.catch(e => console.log('There was a problem: ', e));
```
And there you have it! If you were doing this on testnet, your `fundeeWallet` should now be 1BTC richer. If you're on a simnet or regtest network, you'll have to mine a block with your transactions to get those funds confirmed. Also note that, unless you have exact change coins, there will be 3 transactions that need to be confirmed: one each for the wallets that are splitting coins, and one for the crowdfund transaction.
## How to Build it Out
These examples are obviously pretty basic, but they should give you an idea of how to use Bitcoin's scripting to build out the foundation for more complex applications. Here are some ideas on how you could build on top of these examples and get closer to a production ready application.
- More flexible contribution scheme (currently it's just 2 funders that split the amount evenly). E.g. custom number of contributers, custom contribution amount, etc.
- UX to let people interact with the transaction via a browser
- More advanced interface for fee estimation and include platform for large number of funders (for example, since you may be limited to number of funders per tx, you could include interface for multiple transactions for a single campaign. You would also want to include a check to make sure your tx is not bigger than 100kb otherwise it'll get rejected by the network)
- Add a fund matching scheme where someone can say they will match future contributions
- Currently the examples split transactions to make a coin available that equals the target contribution amount. This is expensive since you have to broadcast multiple transactions. An interface to choose to donate from available available coins might help to make this more efficient.
Make sure to get in touch with us on Twitter or Slack if you build out any of these ideas!
Again, for a working example of the code (without all the text and explanations), check out [the repo on github](https://github.com/Bucko13/bitcoin-fundraise).

35
guides-markdown/multisig-tx.md

@ -29,16 +29,16 @@ signatories chooses a different `m` or a different `n`, they'll end up with diff
You also need to know the pubkey for all cosigners.
You can share these pubkeys however you want. Wallets support various ways for sharing pubkeys, using QR Codes
or sending base58check encoded strings. After you have collected all pubkeys and agreed on `m` and `n`,
you construct the multisig script and generate P2SH address from that.
you construct the multisig script and generate P2SH address from that.
#### Spending Received Transaction
After you've received a transaction on your multisig address, you can spend it if the minimum number of signatures are provided
in a signature script.
1. You need all public keys, the same as were used in address generation.
2. From that you can construct the redeem script, that is the original script you constructed for address.
in a signature script.
1. You need all public keys, the same as were used in address generation.
2. From that you can construct the redeem script, that is the original script you constructed for address.
3. Once you have the redeem script, you can start creating the signature script which will be constructed according
to BIP11 and BIP16.
to BIP11 and BIP16.
4. When you prepend your signature, you take this transaction (not yet fully valid) and send it to another pubkey owner,
who'll be signing next. The next person will do the same, until you have `m` signatures in the sigscript.
@ -55,9 +55,9 @@ After this process is done, your transaction is fully signed and you can broadca
### Manual construction
In this setup, we won't be running a node or running any of the blockchain or wallet functionality of bcoin.
This is a slightly more abstract than constructing bare scripts ourselves.
This is a slightly more abstract than constructing bare scripts ourselves.
We'll split code in multiple files and share keys using the current directory (So you can use fresh dir).
### Step 1: Address Creation
@ -257,14 +257,14 @@ assert(spend2.verify(), 'Transaction isnt valid.');
console.log(spend2.toRaw().toString('hex'));
```
Since there's a lot of code here, I wanted to review a couple of sections.
Since there's a lot of code here, I wanted to review a couple of sections.
This snippet below will return a raw transaction and also makes sure the
transaction has all the signatures.
---
```js
// send change to ourselves
// send change to ourselves
spend1.addOutput({
address: changeAddr,
value: Amount.fromBTC('49.99').toValue()
@ -279,7 +279,7 @@ spend1.addCoin(coin);
In this next snippet we send change to ourselves and specify it manually.
Alternatively, we could also use `MTX.prototype.fund` which automatically
allocates coins to outputs, based on the amounts they need and
also calculate change and append a new output for it.
also calculate change and append a new output for it.
Instead of the code above, we could have simpler and more automated
calculations:
@ -423,7 +423,7 @@ const addSharedKey = async function addSharedKey(client, account, xpubkey, skipR
You will notice that we grab the `.account.accountKey`, first key is the xpubkey
and both will be using xpubkey key derivation to come up with new addresses.
You won't need to share any other public keys, they will derive them for you.
Depth of the account is the only thing you'll need to keep in mind.
Depth of the account is the only thing you'll need to keep in mind.
[addSharedKey](http://bcoin.io/api-docs/index.html#add-xpubkey-multisig) in
wallet/account is used for adding cosigner xpubkeys keys.
@ -431,7 +431,7 @@ wallet/account is used for adding cosigner xpubkeys keys.
We have received transaction
> Transaction ID: 3c12e1b260354fd2a2848030222c4a66339892f1d63b18752ff80ef4eb0197d2
> Transaction ID: c12e1b260354fd2a2848030222c4a66339892f1d63b18752ff80ef4eb0197d2
> Output index: 0
> Amount: 100 BTC
@ -457,7 +457,7 @@ const sendTo = 'RBg1TLaNuRpH6UTFzogFXhjqubPYZaqWgs';
// Because we can't sign and spend from account
// We can't use `spend` as we do with normal transactions
// since it immediately publishes to the network
// since it immediately publishes to the network
// and we need other signatures first.
// So we first create the transaction
const outputs = [{ address: sendTo, value: Amount.fromBTC(1).toValue() }];
@ -470,7 +470,7 @@ const sendTo = 'RBg1TLaNuRpH6UTFzogFXhjqubPYZaqWgs';
// also create changeAddress and calculate fee
const tx1 = await wallet1.createTX(options);
// Now you can share this raw output
// Now you can share this raw output
const raw = tx1.hex;
// Wallet2 will also sign the transaction
@ -485,7 +485,7 @@ const sendTo = 'RBg1TLaNuRpH6UTFzogFXhjqubPYZaqWgs';
});
```
Here you can see it's much cleaner and easier.
Here you can see it's much cleaner and easier.
We still need to manually, using other means, share
raw transaction data for signing.
@ -501,8 +501,9 @@ After that we can just broadcast the transaction to the network.
## Final Notes
I hope, this guide gives you opportunity to understand multisig transactions better and build apps on top of it.
You can play with this code and even build use it in production with small changes (e.g. rate estimation).
I hope this guide gives you the opportunity to better understand multisig transactions and build apps on top of it.
You can play with this code, extend it, and even use it in production with small changes (e.g. rate estimation).
Here are some other ideas for how to build out on top of the app we built in this guide:
- Build UI for configuring and initializing `m` and `n`.

26
guides.html

@ -262,9 +262,10 @@
<ul class="icons-list">
<!-- GUIDES-LIST -->
<li><a href="guides/scripting.html">Intro to Scripting</a></li>
<li><a href="guides/op_return.html">Create an OP_RETURN output transaction</a></li>
<li><a href="guides/op_return.html">Store Data on the Blockchain</a></li>
<li><a href="guides/multisig-tx.html">Creating Multi Signature Transactions</a></li>
<li><a href="guides/generate-address.html">Generate an Address</a></li>
<li><a href="guides/crowdfund-tx.html">Create a Crowdfunding Transaction</a></li>
<!-- /GUIDES-LIST -->
</ul>
</div>
@ -364,7 +365,7 @@
</div> -->
<div class="col-sm-10">
<div class="post-content" style="color:#000;">
<h2 class="post-title"><a href="guides/op_return.html">Create an OP_RETURN output transaction</a></h2>
<h2 class="post-title"><a href="guides/op_return.html">Store Data on the Blockchain</a></h2>
<ul class="post-meta">
<li>By Javed Khan</li>
</ul>
@ -416,6 +417,27 @@
</div>
</div>
</article>
<article class="post format-image">
<div class="row">
<div class="col-sm-1"></div>
<!-- images not used yet
<div class="col-sm-3">
<div class="post-preview">
<a href="#"><img src="assets/images/guides/get-started.png" alt=""></a>
</div>
</div> -->
<div class="col-sm-10">
<div class="post-content" style="color:#000;">
<h2 class="post-title"><a href="guides/crowdfund-tx.html">Create a Crowdfunding Transaction</a></h2>
<ul class="post-meta">
<li>By Buck Perley</li>
</ul>
<p>Learn how SIGHASH flags work in Bitcoin by building out a custom crowdfunding transaction that lets anyone add their own inputs to a transaction with a fixed output.</p>
<a href="guides/crowdfund-tx.html" class="btn btn-lg btn-link btn-base">Start ›</a>
</div>
</div>
</div>
</article>
<!-- END ARCHIVE -->
</div>

811
guides/crowdfund-tx.html

@ -0,0 +1,811 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<title>bcoin | Extending Bitcoin into Enterprise & Production</title>
<!-- Favicons -->
<!-- old
<link rel="shortcut icon" href="../assets/images/bcoin-ico.png">-->
<!-- generated from http://www.favicon-generator.org/ -->
<link rel="apple-touch-icon" sizes="57x57" href="../assets/images/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="../assets/images/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="../assets/images/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="../assets/images/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="../assets/images/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="../assets/images/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="../assets/images/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="../assets/images/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="../assets/images/apple-icon-180x180.png">
<link rel="icon" type="image/png" sizes="192x192" href="../assets/images/android-icon-192x192.png">
<link rel="icon" type="image/png" sizes="32x32" href="../assets/images/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="../assets/images/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="../assets/images/favicon-16x16.png">
<link rel="manifest" href="../assets/images/manifest.json">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="../assets/images/ms-icon-144x144.png">
<meta name="theme-color" content="#ffffff">
<!-- Web Fonts -->
<link href='http://fonts.googleapis.com/css?family=Open+Sans:300,400italic,400,600,700' rel='stylesheet'>
<link href='https://fonts.googleapis.com/css?family=Montserrat:700' rel='stylesheet' type='text/css'>
<!-- Bootstrap core CSS -->
<link href="../assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<!-- Code Snippet CSS -->
<link href="../assets/css/prism.css" rel="stylesheet">
<link href="../assets/css/custom.css" rel="stylesheet">
<!-- Icon Fonts -->
<link href="../assets/css/font-awesome.min.css" rel="stylesheet">
<link href="../assets/css/simple-line-icons.css" rel="stylesheet">
<!-- Plugins -->
<link href="../assets/css/magnific-popup.css" rel="stylesheet">
<link href="../assets/css/owl.carousel.css" rel="stylesheet">
<link href="../assets/css/flexslider.css" rel="stylesheet">
<link href="../assets/css/animate.min.css" rel="stylesheet">
<!-- Template core CSS -->
<link href="../assets/css/vertical.min.css" rel="stylesheet">
<link href="../assets/css/template.css" rel="stylesheet">
<!-- Google Analytics Tracking -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-96446060-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body>
<!-- PRELOADER -->
<div class="page-loader">
<div class="img-loader">Loading...
<!-- Bcoin logo in SVG -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 200 56" style="enable-background:new 0 0 200 56;" xml:space="preserve">
<g id="XMLID_108_">
<g id="XMLID_123_">
<path id="XMLID_124_" d="M8.4,51.8H3.2V4.2h5.2v19.2h0.8c1.2-2,2.8-3.6,4.8-4.7c2-1.1,4.3-1.6,6.7-1.6c2,0,4,0.4,5.8,1.2
c1.8,0.8,3.4,1.9,4.8,3.3c1.4,1.5,2.5,3.2,3.3,5.4s1.2,4.6,1.2,7.3v1.4c0,2.8-0.4,5.2-1.2,7.4c-0.8,2.1-1.9,3.9-3.3,5.4
c-1.4,1.5-3,2.6-4.9,3.3s-3.8,1.1-5.9,1.1c-1.1,0-2.2-0.1-3.3-0.4c-1.1-0.3-2.2-0.6-3.2-1.2c-1-0.5-1.9-1.2-2.8-1.9
c-0.8-0.7-1.6-1.6-2.1-2.7H8.4V51.8z M19.4,47.7c1.6,0,3.1-0.3,4.4-0.9c1.3-0.6,2.5-1.4,3.5-2.4c1-1,1.8-2.3,2.3-3.8
c0.6-1.5,0.8-3.2,0.8-5v-1.4c0-1.8-0.3-3.5-0.8-4.9c-0.6-1.5-1.3-2.7-2.3-3.8c-1-1.1-2.2-1.9-3.5-2.5c-1.4-0.6-2.8-0.9-4.4-0.9
c-1.6,0-3,0.3-4.3,0.9c-1.3,0.6-2.5,1.5-3.5,2.6c-1,1.1-1.8,2.4-2.4,3.9c-0.6,1.5-0.9,3.2-0.9,5v0.8c0,1.9,0.3,3.6,0.9,5.1
c0.6,1.5,1.4,2.8,2.4,3.9s2.2,1.9,3.5,2.5C16.4,47.4,17.9,47.7,19.4,47.7z"/>
</g>
<g id="XMLID_120_">
<path id="XMLID_121_" d="M76.1,39.8c-0.4,1.9-1,3.6-1.8,5.2c-0.9,1.6-2,3-3.3,4.1s-2.9,2.1-4.7,2.7c-1.8,0.6-3.8,1-5.9,1
c-2.3,0-4.5-0.4-6.6-1.2c-2.1-0.8-3.9-1.9-5.4-3.4c-1.6-1.5-2.8-3.3-3.7-5.4c-0.9-2.1-1.4-4.6-1.4-7.4v-0.8c0-2.7,0.5-5.2,1.4-7.4
c0.9-2.2,2.1-4,3.7-5.5c1.6-1.5,3.4-2.7,5.4-3.5c2.1-0.8,4.3-1.2,6.6-1.2c2.1,0,4,0.3,5.8,1c1.8,0.6,3.3,1.5,4.7,2.7
c1.4,1.2,2.5,2.5,3.3,4.1c0.9,1.6,1.5,3.3,1.8,5.2l-5.2,1.2c-0.1-1.2-0.5-2.3-1-3.4c-0.5-1.1-1.2-2.1-2.1-2.9
c-0.9-0.8-1.9-1.5-3.2-2c-1.2-0.5-2.7-0.7-4.3-0.7c-1.6,0-3.1,0.3-4.5,0.9c-1.4,0.6-2.6,1.5-3.7,2.6c-1.1,1.1-1.9,2.4-2.5,4
c-0.6,1.5-0.9,3.2-0.9,5v0.8c0,1.9,0.3,3.6,0.9,5.1c0.6,1.5,1.4,2.8,2.5,3.8c1.1,1,2.3,1.8,3.7,2.4c1.4,0.6,3,0.9,4.6,0.9
s3.1-0.3,4.3-0.8c1.2-0.5,2.3-1.2,3.1-2c0.9-0.8,1.6-1.8,2.1-2.9c0.5-1.1,0.9-2.2,1-3.4L76.1,39.8z"/>
</g>
<g id="XMLID_116_">
<path id="XMLID_117_" d="M117.2,35.4c0,2.8-0.5,5.3-1.4,7.5c-0.9,2.2-2.1,4-3.6,5.4c-1.5,1.5-3.3,2.6-5.3,3.4
c-2,0.8-4.1,1.2-6.3,1.2c-2.2,0-4.3-0.4-6.3-1.2c-2-0.8-3.8-1.9-5.3-3.4c-1.5-1.5-2.7-3.3-3.6-5.4c-0.9-2.2-1.4-4.6-1.4-7.5v-0.8
c0-2.8,0.5-5.2,1.4-7.4c0.9-2.2,2.1-4,3.7-5.5c1.5-1.5,3.3-2.6,5.3-3.4c2-0.8,4.1-1.2,6.3-1.2c2.2,0,4.3,0.4,6.3,1.2
c2,0.8,3.8,1.9,5.3,3.4c1.5,1.5,2.8,3.3,3.7,5.5c0.9,2.2,1.4,4.6,1.4,7.4V35.4z M100.6,47.7c1.6,0,3.1-0.3,4.4-0.9
c1.4-0.6,2.5-1.4,3.6-2.5c1-1.1,1.8-2.4,2.4-3.9c0.6-1.5,0.9-3.2,0.9-5.1v-0.8c0-1.8-0.3-3.5-0.9-5c-0.6-1.5-1.4-2.8-2.4-3.9
c-1-1.1-2.2-1.9-3.6-2.6c-1.4-0.6-2.8-0.9-4.4-0.9c-1.6,0-3,0.3-4.4,0.9c-1.4,0.6-2.6,1.5-3.6,2.6c-1,1.1-1.8,2.4-2.4,3.9
c-0.6,1.5-0.9,3.2-0.9,5v0.8c0,1.9,0.3,3.6,0.9,5.1c0.6,1.5,1.4,2.8,2.4,3.9c1,1.1,2.2,1.9,3.6,2.5C97.5,47.5,99,47.7,100.6,47.7z
"/>
</g>
<g id="XMLID_112_">
<path id="XMLID_113_" d="M127.6,46.9h11.6V23h-10.4v-4.9h15.6v28.9h10.8v4.9h-27.6V46.9z M137.1,8c0-1.3,0.5-2.4,1.4-3.4
c0.9-0.9,2-1.4,3.3-1.4c1.3,0,2.4,0.5,3.3,1.4c0.9,0.9,1.4,2.1,1.4,3.4c0,1.3-0.5,2.4-1.4,3.4c-0.9,0.9-2,1.4-3.3,1.4
c-1.3,0-2.4-0.5-3.3-1.4C137.5,10.4,137.1,9.3,137.1,8z"/>
</g>
<g id="XMLID_109_">
<path id="XMLID_110_" d="M172.8,51.8h-5.2V18.1h5.2v5.7h0.8c2-4.4,5.6-6.7,10.7-6.7c3.8,0,6.9,1.2,9.1,3.6
c2.3,2.4,3.4,6.1,3.4,10.9v20.2h-5.2V32.8c0-3.5-0.8-6.2-2.3-8c-1.6-1.8-3.7-2.7-6.3-2.7c-3.2,0-5.6,1.1-7.4,3.3s-2.7,5.1-2.7,8.8
V51.8z"/>
</g>
</g>
</svg>
</div>
</div>
<!-- END PRELOADER -->
<!-- HEADER -->
<header class="header js-stick">
<div class="container">
<!-- YOUR LOGO HERE -->
<div class="inner-header">
<a class="inner-brand" href="../index.html">
<img class="brand-light" src="../assets/images/logo-light.png" width="100" alt="">
<img class="brand-dark" src="../assets/images/logo-dark.png" width="100" alt="">
</a>
</div>
<!-- OPEN MOBILE MENU -->
<div class="main-nav-toggle">
<div class="nav-icon-toggle" data-toggle="collapse" data-target="#custom-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</div>
</div>
<!-- WIDGETS MENU -->
<div class="inner-header pull-right hide-me">
<div class="menu-extras clearfix">
<!-- SLACK LINK -->
<div class="menu-item">
<div class="">
<a href="../slack-signup.html" target="_blank" id="" data-toggle="tooltip" title="" data-placement="bottom" data-original-title="Join us on Slack!">
<img src="../assets/images/slack_icon.svg" width="18" height="18"/>
<span class=""></span>
</a>
</div>
</div>
<!-- STACK EXCHANGE LINK -->
<div class="menu-item">
<div class="">
<a href="https://bitcoin.stackexchange.com/questions/tagged/bcoin" target="_blank" id="" data-toggle="tooltip" title="" data-placement="bottom" data-original-title="Questions! Checkout Stack Exchange.">
<img src="../assets/images/stack-exchange-icon.svg" width="18" height="18"/>
<span class=""></span>
</a>
</div>
</div>
<!-- GITHUB STUFF -->
<div class="menu-item">
<div class="">
<a href="https://github.com/bcoin-org/bcoin" target="_blank" id="" data-toggle="tooltip" title="" data-placement="bottom" data-original-title="Visit bcoin on GitHub to see the code!">
<img src="../assets/images/github_icon.svg" width="18" height="18"/>
<span class=""></span>
</a>
</div>
</div>
<div class="menu-item">
<div class="ghbuttons">
<a class="github-button" href="https://github.com/bcoin-org/bcoin" data-icon="octicon-star" data-count-href="/bcoin-org/bcoin/stargazers" data-show-count="true" data-count-aria-label="# stargazers on GitHub" aria-label="Star bcoin-org/bcoin on GitHub">Star</a>
<a class="github-button" href="https://github.com/bcoin-org/bcoin/fork" data-icon="octicon-repo-forked" data-count-href="/bcoin-org/bcoin/network" data-show-count="true" data-count-aria-label="# forks on GitHub" aria-label="Fork bcoin-org/bcoin on GitHub">Fork</a>
</div>
</div>
</div>
</div>
<!-- MAIN MENU -->
<nav id="custom-collapse" class="main-nav collapse clearfix">
<ul class="inner-nav pull-right">
<!-- HOME -->
<li><a href="../index.html">Home</a></li>
<!-- END HOME -->
<!-- FEATURES -->
<li><a href="../index.html#features">What is Bcoin</a></li>
<!-- END FEATURES -->
<!-- GUIDES -->
<li><a href="../guides.html">Guides</a></li>
<!-- GUIDES -->
<!-- API REFERENCE - newer, how to interact once you're setup -->
<li><a href="../api-docs/index.html">API Docs</a></li>
<!-- END API -->
<!-- FULL DOCS - older, full reference
<li><a href="http://bcoin.io/docs/index.html">Docs</a></li> -->
<!-- END DOCS -->
<!-- DIVIDER
<li><a>&nbsp;</a></li>
<li><a href="#">All Demos</a></li>-->
</ul>
</nav>
</div>
</header>
<!-- END HEADER -->
<!-- WRAPPER -->
<div class="wrapper">
<!-- PAGE TITLE -->
<section class="module-sm bg-white-dark" data-background="../assets/images/bg-header.jpg">
<div class="container">
<div class="row">
<div class="col-sm-12 text-center">
<h2 class="montserrat text-uppercase m-b-10"><span class="text-highlight-black" style="line-height: 1.5;">&nbsp;Guides &nbsp;and &nbsp;Videos&nbsp;</span></h2>
</div>
</div>
</div>
</section>
<!-- END PAGE TITLE -->
<!-- GUIDES/TUTORIALS -->
<section class="module" style="padding-top:70px !important;">
<div class="container">
<div class="row">
<!-- START SIDEBAR -->
<div class="col-sm-3 sidebar">
<!-- CATEGORIES WIDGET -->
<div class="widget guide-list">
<h6 class="montserrat text-uppercase bottom-line">Install</h6>
<ul class="icons-list">
<!-- INSTALL-LIST -->
<li><a href="install-windows.html">Install on Windows (Video)</a></li>
<li><a href="install-mac.html">Install on Mac OS (Video)</a></li>
<li><a href="install-linux.html">Install on Linux (Video)</a></li>
<!-- /INSTALL-LIST -->
</ul>
<br>
<h6 class="montserrat text-uppercase bottom-line">Guides</h6>
<ul class="icons-list">
<!-- GUIDES-LIST -->
<li><a href="scripting.html">Intro to Scripting</a></li>
<li><a href="op_return.html">Store Data on the Blockchain</a></li>
<li><a href="multisig-tx.html">Creating Multi Signature Transactions</a></li>
<li><a href="generate-address.html">Generate an Address</a></li>
<li><a href="crowdfund-tx.html">Create a Crowdfunding Transaction</a></li>
<!-- /GUIDES-LIST -->
</ul>
</div>
<!-- END CATEGORIES WIDGET -->
<!-- TEXT WIDGET -->
<div class="widget">
<h6 class="montserrat text-uppercase bottom-line">Looking for Docs?</h6>
<p>Checkout our <a href="../api-docs/index.html">API Docs</a> or the <a href="http://bcoin.io/docs/index.html">Full Documentation</a></p>
</div>
<!-- END TEXT WIDGET -->
<!-- TEXT WIDGET -->
<div class="widget">
<h6 class="montserrat text-uppercase bottom-line">Get Involved</h6>
<p>If you think you've got what it takes to make your own bcoin guides and tutorials, reach out to us on <a href="../slack-signup.html"> Slack!</a></p>
<p>Want to join the team?<a href="https://angel.co/purse/jobs/90956-bitcoin-protocol-engineer-bcoin"> We’re hiring.</a></p>
</div>
<!-- END TEXT WIDGET -->
</div>
<!-- END SIDEBAR -->
<!-- START OF ARTICLE CONTAINER -->
<div class="col-sm-9 blog-content post-thumbnail">
<!-- POST IMAGE -->
<article class="post format-image">
<div class="row">
<!--<div class="col-sm-5">
<div class="post-preview">
<a href="#"><img src="../assets/images/guides/get-started.png" alt=""></a>
</div>
</div>-->
<!-- after re-enabling the above code, change the col-sm below to col-sm-7 -->
<div class="panel-group">
<div class="col-sm-12 panel panel-default">
<div class="post-content" style="color:#000;">
<!-- START OF GUIDE -->
<h2 class="post-title panel-title" id="create-a-crowdfunding-transaction">Create a Crowdfunding Transaction</h2><ul class="post-meta"><li class="author">By Buck Perley</li></ul><h2 id="sighash-flags">SIGHASH Flags</h2><p>In most Bitcoin transactions, when a transaction is signed, the entirety of the data in that transaction is committed to in that input&#39;s signature, with all outputs and inputs being included in the unlocking script. This, however, doesn&#39;t always have to be the case. The level of commitment is indicated by using <code>SIGHASH</code> flags. The most common flag is <code>SIGHASH_ALL</code> which has a value of 0x01 (you&#39;ll see this represented as a <code>01</code> at the end of DER-encoded signatures). To learn more about how the flags work and what other options are available, you should checkout <a href="https://github.com/bitcoinbook/bitcoinbook/blob/8d01749bcf45f69f36cf23606bbbf3f0bd540db3/ch06.asciidoc">Chapter 6</a> of <em>Mastering Bitcoin</em> by Andreas Antonopolous. In that chapter, Andreas posits one novel use of a specialized flag, <code>ALL|ANYONECANPAY</code>, and in this guide we&#39;ll try and build out a couple of examples implementing this idea using bcoin.</p>
<h2 id="how-it-works">How it Works</h2><p>The <code>ALL|ANYONECANPAY</code> flag indicates that a signature is committing all of the outputs and just one input. The suggested use case of this proposed in <em>Mastering Bitcoin</em> is a kickstarter-like crowdfunding application. Consider the situation where you have a fundraising goal, say 1BTC. You&#39;d like multiple people to contribute to your goal and you want to prove to them that they won&#39;t have to pay <em>unless</em> you reach your goal (i.e. the transaction is invalid and won&#39;t be accepted by the network if attempted to be sent). This means you&#39;d be committing to one output, the one that sends the funds to the charity or project you&#39;d like to donate to, and only one input, your contribution. This allows multiple users to contribute to the same transaction and that transaction won&#39;t be valid until it&#39;s fully funded.</p>
<p>Here&#39;s how it&#39;s explained in <em>Mastering Bitcoin</em>:</p>
<blockquote>
<p>ALL|ANYONECANPAY
This construction can be used to make a &quot;crowdfunding”-style transaction. Someone attempting to raise funds can construct a transaction with a single output. The single output pays the &quot;goal&quot; amount to the fundraiser. Such a transaction is obviously not valid, as it has no inputs. However, others can now amend it by adding an input of their own, as a donation. They sign their own input with ALL|ANYONECANPAY. Unless enough inputs are gathered to reach the value of the output, the transaction is invalid. Each donation is a &quot;pledge,&quot; which cannot be collected by the fundraiser until the entire goal amount is raised.</p>
</blockquote>
<h2 id="the-code">The Code</h2><p>We&#39;ll walk through the steps of creating the transaction first without any wallet database or node running. Then we&#39;ll do the same thing using bcoin&#39;s walletdb to manage the keys to see how it would work in a more realistic application (skip to <a href="#version-2-using-the-bcoin-wallet-system">Version 2</a>) further in the guide to check it out). At the end, we&#39;ll put out some ideas of how these can be built upon for a more robust, production ready application. (If this is something you&#39;d be interested in building, <a href="http://bcoin.io/slack-signup.html">get in touch</a>!). If you want to see the code, checkout the <a href="https://github.com/Bucko13/bitcoin-fundraise">repo on github</a>.</p>
<p>If you&#39;re not comfortable with key management, coin selection, and how transactions are constructed, checkout the tutorial on <a href="https://github.com/bcoin-org/bcoin/blob/master/docs/Working-with-transactions.md">working with transactions</a> first.</p>
<h3 id="version-1--manual-key-management">Version 1 - Manual Key Management</h3><h4 id="step-1-setup">Step 1: Setup</h4><p>Let&#39;s first start by importing the right tools, setting up some constants, and creating our keychains. (make sure you&#39;ve installed the latest version of bcoin into your project with <code>npm install bcoin</code>).</p>
<p>Note that we&#39;re setting the fundingTarget and amountToFund as constants for simplicity, but they could be set based on user input or some other variable circumstances.</p>
<pre class="snippet line-numbers language-javascript"><code class="line-numbers language-javascript"><span class="token string">'use strict'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> assert <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'assert'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> bcoin <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'bcoin'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> MTX <span class="token operator">=</span> bcoin<span class="token punctuation">.</span>mtx<span class="token punctuation">;</span>
<span class="token keyword">const</span> Keyring <span class="token operator">=</span> bcoin<span class="token punctuation">.</span>keyring<span class="token punctuation">;</span>
<span class="token keyword">const</span> Outpoint <span class="token operator">=</span> bcoin<span class="token punctuation">.</span>outpoint<span class="token punctuation">;</span>
<span class="token keyword">const</span> Script <span class="token operator">=</span> bcoin<span class="token punctuation">.</span>script<span class="token punctuation">;</span>
<span class="token keyword">const</span> Coin <span class="token operator">=</span> bcoin<span class="token punctuation">.</span>coin<span class="token punctuation">;</span>
<span class="token keyword">const</span> policy <span class="token operator">=</span> bcoin<span class="token punctuation">.</span>protocol<span class="token punctuation">.</span>policy
<span class="token keyword">const</span> fundingTarget <span class="token operator">=</span> <span class="token number">100000000</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 1 BTC</span>
<span class="token keyword">const</span> amountToFund <span class="token operator">=</span> <span class="token number">50000000</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// .5 BTC</span>
<span class="token keyword">const</span> txRate <span class="token operator">=</span> <span class="token number">10000</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 10000 satoshis/kb</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><p>Let&#39;s derive private hd key for fundee and two funders and create a &quot;keyring&quot; object for each (much of this is borrowed from the <em>Working with Transactions</em> guide).</p>
<p>A keyring object is basically a key manager that is also able to tell you info such as:</p>
<ul>
<li>your redeem script</li>
<li>your scripthash</li>
<li>your program hash</li>
<li>your pubkey hash</li>
<li>your scripthash program hash</li>
</ul>
<pre class="snippet line-numbers language-javascript"><code class="line-numbers language-javascript"><span class="token comment" spellcheck="true">// Create an HD master keypair.</span>
<span class="token keyword">const</span> master <span class="token operator">=</span> bcoin<span class="token punctuation">.</span>hd<span class="token punctuation">.</span><span class="token function">generate</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> fundeeKey <span class="token operator">=</span> master<span class="token punctuation">.</span><span class="token function">derive</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> fundeeKeyring <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Keyring</span><span class="token punctuation">(</span>fundeeKey<span class="token punctuation">.</span>privateKey<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> fundeeAddress <span class="token operator">=</span> fundeeKeyring<span class="token punctuation">.</span><span class="token function">getAddress</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// Derive 2 more private hd keys and keyrings for funders</span>
<span class="token keyword">const</span> funder1Key <span class="token operator">=</span> master<span class="token punctuation">.</span><span class="token function">derive</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> funder1Keyring <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Keyring</span><span class="token punctuation">(</span>funder1Key<span class="token punctuation">.</span>privateKey<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> funder2Key <span class="token operator">=</span> master<span class="token punctuation">.</span><span class="token function">derive</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> funder2Keyring <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Keyring</span><span class="token punctuation">(</span>funder2Key<span class="token punctuation">.</span>privateKey<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> funders <span class="token operator">=</span> <span class="token punctuation">[</span>funder1Keyring<span class="token punctuation">,</span> funder2Keyring<span class="token punctuation">]</span><span class="token punctuation">;</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><h4 id="step-2-fund-the-keyrings">Step 2: Fund the Keyrings</h4><p>This example is working in an isolated environment, so it won&#39;t work on the actual network (main, test, or otherwise), but we also don&#39;t have to earn or send ourselves coins or wait for confirmation times. That means that we can &quot;spawn&quot; coins for our funder wallets that they can use to spend on the crowdfunding platform.</p>
<p>Let&#39;s create some coinbase transactions to give our keyrings some coins that they can spend.</p>
<pre class="snippet line-numbers language-javascript"><code class="line-numbers language-javascript"><span class="token comment" spellcheck="true">// create some coinbase transactions to fund our wallets</span>
<span class="token keyword">const</span> coins <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> i<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> funders<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> cb <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MTX</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// Add a typical coinbase input</span>
cb<span class="token punctuation">.</span><span class="token function">addInput</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
prevout<span class="token punctuation">:</span> <span class="token keyword">new</span> <span class="token class-name">Outpoint</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
script<span class="token punctuation">:</span> <span class="token keyword">new</span> <span class="token class-name">Script</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
cb<span class="token punctuation">.</span><span class="token function">addOutput</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
address<span class="token punctuation">:</span> funders<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">getAddress</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
value<span class="token punctuation">:</span> <span class="token number">500000000</span> <span class="token comment" spellcheck="true">// give the funder 5BTC</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">assert</span><span class="token punctuation">(</span>cb<span class="token punctuation">.</span>inputs<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">isCoinbase</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// Convert the coinbase output to a Coin</span>
<span class="token comment" spellcheck="true">// object and add it to the available coins for that keyring.</span>
<span class="token comment" spellcheck="true">// In reality you might get these coins from a wallet.</span>
coins<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span>Coin<span class="token punctuation">.</span><span class="token function">fromTX</span><span class="token punctuation">(</span>cb<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><p>The coins object you&#39;ve created above should look something like this:</p>
<pre class="snippet line-numbers language-json"><code class="line-numbers language-json"><span class="token punctuation">{</span>
<span class="token property">"0"</span><span class="token operator">:</span>
<span class="token punctuation">[</span>
<span class="token punctuation">{</span>
<span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"pubkeyhash"</span><span class="token punctuation">,</span>
<span class="token property">"version"</span><span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
<span class="token property">"height"</span><span class="token operator">:</span> -<span class="token number">1</span><span class="token punctuation">,</span>
<span class="token property">"value"</span><span class="token operator">:</span> <span class="token string">"5.0"</span><span class="token punctuation">,</span>
<span class="token property">"script"</span><span class="token operator">:</span> &lt;Script<span class="token operator">:</span> OP_DUP OP_HASH160 <span class="token number">0x14</span> <span class="token number">0x64cc4e55b2daec25431bd879ef39302a77c1c1ce</span> OP_EQUALVERIFY OP_CHECKSIG><span class="token punctuation">,</span>
<span class="token property">"coinbase"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
<span class="token property">"hash"</span><span class="token operator">:</span> <span class="token string">"151e5551cdcec5fff06818fb78ac3d584361276e862b5700110ec8321869d650"</span><span class="token punctuation">,</span>
<span class="token property">"index"</span><span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
<span class="token property">"address"</span><span class="token operator">:</span> &lt;Address<span class="token operator">:</span> type=pubkeyhash version=-<span class="token number">1</span> str=mphvcfcFneRZvyYsmzhy57cSDzFbGrWaRb>
<span class="token punctuation">}</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token property">"1"</span><span class="token operator">:</span> <span class="token punctuation">[</span>...<span class="token punctuation">]</span>
<span class="token punctuation">}</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><h4 id="step-4-prepare-your-coins">Step 4: Prepare your Coins</h4><p>Above, we just funded our funder accounts with a single 5BTC outpoint. This means that the next transaction funded from these accounts can only use that one outpoint (or <em>coin</em>) as an input and send the remainder back as change. Remember, in Bitcoin the way you send funds is you fund a transaction with a full UTXO (in this case we only have one worth 5BTC available to our keychains) and then send the change back to yourself as an additional output. Since ALL|ANYONECANPAY transactions mean a fixed output, you can&#39;t add new change outputs without other signatures becoming invalid which means we need a coin available equal to the amount we want to contribute to the crowdfund.</p>
<p>So what we want to do is have each funder create a coin (UTXO) with the value of what they want to donate.</p>
<p>The first thing we need to do make this work is calculate what the input will be. In our examples we are assuming that the funders cover the fee. Since different keyrings can be using different transaction types of different sizes (p2sh, multisig, etc.), we need a utility to calculate how much the fee should be for that input and add that to the amount to fund with.</p>
<h5 id="utility-functions">Utility functions</h5><p>We&#39;ll need some utility functions to help us out. It&#39;s nice to split these out separate from our main operations since we&#39;ll actually be reusing some of the functionality.</p>
<p>Before we build out the tools to calculate fees and split coins, we&#39;ll need a utility for composing the inputs for txs that we&#39;ll use for our mock transactions in the fee calculator and later for templating our real transaction</p>
<pre class="snippet line-numbers language-javascript"><code class="line-numbers language-javascript"><span class="token keyword">const</span> addInput <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token function">addInput</span><span class="token punctuation">(</span>coin<span class="token punctuation">,</span> inputIndex<span class="token punctuation">,</span> mtx<span class="token punctuation">,</span> keyring<span class="token punctuation">,</span> hashType<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> sampleCoin <span class="token operator">=</span> coin <span class="token keyword">instanceof</span> <span class="token class-name">Coin</span> <span class="token operator">?</span> coin <span class="token punctuation">:</span> Coin<span class="token punctuation">.</span><span class="token function">fromJSON</span><span class="token punctuation">(</span>coin<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>hashType<span class="token punctuation">)</span> hashType <span class="token operator">=</span> Script<span class="token punctuation">.</span>hashType<span class="token punctuation">.</span>ANYONECANPAY <span class="token operator">|</span> Script<span class="token punctuation">.</span>hashType<span class="token punctuation">.</span>ALL<span class="token punctuation">;</span>
mtx<span class="token punctuation">.</span><span class="token function">addCoin</span><span class="token punctuation">(</span>sampleCoin<span class="token punctuation">)</span><span class="token punctuation">;</span>
mtx<span class="token punctuation">.</span><span class="token function">scriptInput</span><span class="token punctuation">(</span>inputIndex<span class="token punctuation">,</span> sampleCoin<span class="token punctuation">,</span> keyring<span class="token punctuation">)</span><span class="token punctuation">;</span>
mtx<span class="token punctuation">.</span><span class="token function">signInput</span><span class="token punctuation">(</span>inputIndex<span class="token punctuation">,</span> sampleCoin<span class="token punctuation">,</span> keyring<span class="token punctuation">,</span> hashType<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">assert</span><span class="token punctuation">(</span>mtx<span class="token punctuation">.</span><span class="token function">isSigned</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'Input was not signed properly'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><p>Now let&#39;s build the utility for calculating the fee for a single input of unknown type or size</p>
<pre class="snippet line-numbers language-javascript"><code class="line-numbers language-javascript"><span class="token keyword">const</span> getFeeForInput <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token function">getFeeForInput</span><span class="token punctuation">(</span>coin<span class="token punctuation">,</span> address<span class="token punctuation">,</span> keyring<span class="token punctuation">,</span> rate<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> fundingTarget <span class="token operator">=</span> <span class="token number">100000000</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 1 BTC (arbitrary for purposes of this function)</span>
<span class="token keyword">const</span> testMTX <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MTX</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// we're not actually going to use this tx for anything other than calculate what fee should be</span>
<span class="token function">addInput</span><span class="token punctuation">(</span>coin<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> testMTX<span class="token punctuation">,</span> keyring<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> testMTX<span class="token punctuation">.</span><span class="token function">getMinFee</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">,</span> rate<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><p>Our last utility is an asyncronous function to help us split the coinbases we created in the previous step (we use the <code>fund</code> method on the <code>MTX</code> primitive to do this, which is asynchronous).</p>
<pre class="snippet line-numbers language-javascript"><code class="line-numbers language-javascript"><span class="token keyword">const</span> splitCoinbase <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">splitCoinbase</span><span class="token punctuation">(</span>funderKeyring<span class="token punctuation">,</span> coin<span class="token punctuation">,</span> targetAmount<span class="token punctuation">,</span> txRate<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment" spellcheck="true">// loop through each coinbase coin to split</span>
<span class="token keyword">let</span> coins <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> mtx <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MTX</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">assert</span><span class="token punctuation">(</span>coin<span class="token punctuation">.</span>value <span class="token operator">></span> targetAmount<span class="token punctuation">,</span> <span class="token string">'coin value is not enough!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// creating a transaction that will have an output equal to what we want to fund</span>
mtx<span class="token punctuation">.</span><span class="token function">addOutput</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
address<span class="token punctuation">:</span> funderKeyring<span class="token punctuation">.</span><span class="token function">getAddress</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
value<span class="token punctuation">:</span> targetAmount
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// the fund method will automatically split</span>
<span class="token comment" spellcheck="true">// the remaining funds to the change address</span>
<span class="token comment" spellcheck="true">// Note that in a real application these splitting transactions will also</span>
<span class="token comment" spellcheck="true">// have to be broadcast to the network</span>
<span class="token keyword">await</span> mtx<span class="token punctuation">.</span><span class="token function">fund</span><span class="token punctuation">(</span><span class="token punctuation">[</span>coin<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
rate<span class="token punctuation">:</span> txRate<span class="token punctuation">,</span>
<span class="token comment" spellcheck="true">// send change back to an address belonging to the funder</span>
changeAddress<span class="token punctuation">:</span> funderKeyring<span class="token punctuation">.</span><span class="token function">getAddress</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token punctuation">{</span>
<span class="token comment" spellcheck="true">// sign the mtx to finalize split</span>
mtx<span class="token punctuation">.</span><span class="token function">sign</span><span class="token punctuation">(</span>funderKeyring<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">assert</span><span class="token punctuation">(</span>mtx<span class="token punctuation">.</span><span class="token function">verify</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> tx <span class="token operator">=</span> mtx<span class="token punctuation">.</span><span class="token function">toTX</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">assert</span><span class="token punctuation">(</span>tx<span class="token punctuation">.</span><span class="token function">verify</span><span class="token punctuation">(</span>mtx<span class="token punctuation">.</span>view<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> outputs <span class="token operator">=</span> tx<span class="token punctuation">.</span>outputs<span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// get coins from tx</span>
outputs<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span>outputs<span class="token punctuation">,</span> index<span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token punctuation">{</span>
coins<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>Coin<span class="token punctuation">.</span><span class="token function">fromTX</span><span class="token punctuation">(</span>tx<span class="token punctuation">,</span> index<span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token keyword">catch</span><span class="token punctuation">(</span>e <span class="token operator">=</span><span class="token operator">></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'There was an error: '</span><span class="token punctuation">,</span> e<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> coins<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><p>Because of the async methods being used, in order to take advantage of the async/await structure, the rest of the code will be enclosed in an async function.</p>
<p>The first thing we&#39;ll do is split the coinbase coins we created earlier using the utility function we just built (we&#39;ll also have to calculate the fee and add it to the funding amount in order to get an output of the right value).</p>
<pre class="snippet line-numbers language-javascript"><code class="line-numbers language-javascript"><span class="token keyword">const</span> composeCrowdfund <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">composeCrowdfund</span><span class="token punctuation">(</span>coins<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> funderCoins <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// Loop through each coinbase</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> index <span class="token keyword">in</span> coins<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> coinbase <span class="token operator">=</span> coins<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// estimate fee for each coin (assuming their split coins will use same tx type)</span>
<span class="token keyword">const</span> estimatedFee <span class="token operator">=</span> <span class="token function">getFeeForInput</span><span class="token punctuation">(</span>coinbase<span class="token punctuation">,</span> fundeeAddress<span class="token punctuation">,</span> funders<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">,</span> txRate<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> targetPlusFee <span class="token operator">=</span> amountToFund <span class="token operator">+</span> estimatedFee<span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// split the coinbase with targetAmount plus estimated fee</span>
<span class="token keyword">const</span> splitCoins <span class="token operator">=</span> <span class="token keyword">await</span> Utils<span class="token punctuation">.</span><span class="token function">splitCoinbase</span><span class="token punctuation">(</span>funders<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">,</span> coinbase<span class="token punctuation">,</span> targetPlusFee<span class="token punctuation">,</span> txRate<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// add to funderCoins object with returned coins from splitCoinbase being value,</span>
<span class="token comment" spellcheck="true">// and index being the key</span>
funderCoins<span class="token punctuation">[</span>index<span class="token punctuation">]</span> <span class="token operator">=</span> splitCoins<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment" spellcheck="true">// ... we'll keep filling out the rest of the code here</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><p><code>funderCoins</code> should return x number of coin arrays, where X is the number of coinbases we created earlier (should be 2) with each array having a coin equal to the amount we want to donate.</p>
<p>For example...</p>
<pre class="snippet line-numbers language-json"><code class="line-numbers language-json"><span class="token punctuation">{</span>
<span class="token property">"0"</span><span class="token operator">:</span>
<span class="token punctuation">[</span>
<span class="token punctuation">{</span>
<span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"pubkeyhash"</span><span class="token punctuation">,</span>
<span class="token property">"version"</span><span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
<span class="token property">"height"</span><span class="token operator">:</span> -<span class="token number">1</span><span class="token punctuation">,</span>
<span class="token property">"value"</span><span class="token operator">:</span> <span class="token string">"0.5000157"</span>
<span class="token property">"script"</span><span class="token operator">:</span> &lt;Script<span class="token operator">:</span> OP_DUP OP_HASH160 <span class="token number">0x14</span> <span class="token number">0x62f725e83caf894aa6c3efd29ef28649fc448825</span> OP_EQUALVERIFY OP_CHECKSIG><span class="token punctuation">,</span>
<span class="token property">"coinbase"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
<span class="token property">"hash"</span><span class="token operator">:</span> <span class="token string">"774822d84bd5af02f1b3eacd6215e0a1bcf07cfb6675a000c8a01d2ea34f2a32"</span><span class="token punctuation">,</span>
<span class="token property">"index"</span><span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
<span class="token property">"address"</span><span class="token operator">:</span> &lt;Address<span class="token operator">:</span> type=pubkeyhash version=-<span class="token number">1</span> str=mpYEb17KR7MVhuPZT1GsW3SywZx8ihYube>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
...
<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token property">"1"</span><span class="token operator">:</span> <span class="token punctuation">[</span>...<span class="token punctuation">]</span>
<span class="token punctuation">}</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><h4 id="step-6-construct-the-transaction">Step 6: Construct the Transaction</h4><p>Now that we&#39;ve got our tools and coins ready, we can start to build the transaction!</p>
<pre class="snippet line-numbers language-javascript"><code class="line-numbers language-javascript"><span class="token keyword">const</span> composeCrowdfund <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">composeCrowdfund</span><span class="token punctuation">(</span>coins<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment" spellcheck="true">//...</span>
<span class="token keyword">const</span> fundMe <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MTX</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// add an output with the target funding amount</span>
fundMe<span class="token punctuation">.</span><span class="token function">addOutput</span><span class="token punctuation">(</span><span class="token punctuation">{</span> value<span class="token punctuation">:</span> fundingTarget<span class="token punctuation">,</span> address<span class="token punctuation">:</span> fundeeAddress <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// fund with first funder</span>
<span class="token keyword">let</span> fundingCoin <span class="token operator">=</span> funderCoins<span class="token punctuation">[</span><span class="token string">'0'</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token function">addInput</span><span class="token punctuation">(</span>fundingCoin<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> fundMe<span class="token punctuation">,</span> funder1Keyring<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// fund with second funder</span>
fundingCoin <span class="token operator">=</span> funderCoins<span class="token punctuation">[</span><span class="token string">'1'</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token function">addInput</span><span class="token punctuation">(</span>fundingCoin<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> fundMe<span class="token punctuation">,</span> funder2Keyring<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// We want to confirm that total value of inputs covers the funding goal</span>
<span class="token comment" spellcheck="true">// NOTE: the difference goes to the miner in the form of fees</span>
<span class="token function">assert</span><span class="token punctuation">(</span>fundMe<span class="token punctuation">.</span><span class="token function">getInputValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">>=</span> fundMe<span class="token punctuation">.</span>outputs<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>value<span class="token punctuation">,</span> <span class="token string">'Total inputs not enough to fund'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">assert</span><span class="token punctuation">(</span>fundMe<span class="token punctuation">.</span><span class="token function">verify</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'The mtx is malformed'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> tx <span class="token operator">=</span> fundMe<span class="token punctuation">.</span><span class="token function">toTX</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'total input value = '</span><span class="token punctuation">,</span> fundMe<span class="token punctuation">.</span><span class="token function">getInputValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Fee getting sent to miners:'</span><span class="token punctuation">,</span> fundMe<span class="token punctuation">.</span><span class="token function">getInputValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span> fundingTarget<span class="token punctuation">,</span> <span class="token string">'satoshis'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">assert</span><span class="token punctuation">(</span>tx<span class="token punctuation">.</span><span class="token function">verify</span><span class="token punctuation">(</span>fundMe<span class="token punctuation">.</span>view<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'there is a problem with your tx'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> tx<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token function">composeCrowdfund</span><span class="token punctuation">(</span>coins<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span>myCrowdfundTx <span class="token operator">=</span><span class="token operator">></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>myCrowdfundTx<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><p><code>composeCrowdfund</code> will now return a promise (thanks to async/await) that returns a fully templated transaction that can be transmitted to the network. It should have two inputs and one output with a value of 1. The inputs will have a value equal to the amount to fund plus the cost of the fee. You should also notice the <code>SIGHASH</code> flag 0x81 at the end of the input scripts which confirms they are <code>ALL|ANYONECANPAY</code> scripts.</p>
<h3 id="version-2-using-the-bcoin-wallet-system">Version 2: Using the Bcoin Wallet System</h3><p>Since trying to manage your own keys is pretty tedious, not to mention impractical especially if you want to let other people contribute to your campaign, let&#39;s use the bcoin wallet system to take care of that part of the process. For the this example, we&#39;re going to interact via the wallet client, but you could also do something similar within a bcoin node (using the wallet and walletdb directly) which would also be more secure.</p>
<p>Note that this is a little more tedious to test since you need to have funded wallets in order to actually fund your campaign. You can find a bitcoin testnet faucet to get some funds to play with or, as we will do in this example, create your own simnet or regtest network where you mine your own blocks to fund yourself.</p>
<h4 id="step-1-setup-our-wallets">Step 1: Setup Our Wallets</h4><p>We&#39;ll skip the setup of constants import modules since we can use the same from the previous example. Since there are a lot of asynchronous operations here now that we&#39;re using the client, we&#39;ll also put this in an async function and will continue to build out the contents of the function throughout this guide. We&#39;ll also be using some of the same <a href="#utility-functions">utility functions that we created in the last example</a>.</p>
<pre class="snippet line-numbers language-javascript"><code class="line-numbers language-javascript"><span class="token keyword">const</span> network <span class="token operator">=</span> <span class="token string">'regtest'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> composeWalletCrowdfund <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">composeWalletCrowdfund</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> client <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token keyword">new</span> <span class="token class-name">bcoin<span class="token punctuation">.</span>http<span class="token punctuation">.</span>Client</span><span class="token punctuation">(</span><span class="token punctuation">{</span> network <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// Step 1: Setup our wallets and funding targets</span>
<span class="token keyword">const</span> fundeeWallet <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token keyword">new</span> <span class="token class-name">httpWallet</span><span class="token punctuation">(</span><span class="token punctuation">{</span> id<span class="token punctuation">:</span> <span class="token string">'fundee'</span><span class="token punctuation">,</span> network <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> fundeeAddress <span class="token operator">=</span> <span class="token keyword">await</span> fundeeWallet<span class="token punctuation">.</span><span class="token function">createAddress</span><span class="token punctuation">(</span><span class="token string">'default'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> funders <span class="token operator">=</span> <span class="token punctuation">{</span>
<span class="token string">'funder1'</span><span class="token punctuation">:</span> <span class="token keyword">await</span> <span class="token keyword">new</span> <span class="token class-name">httpWallet</span><span class="token punctuation">(</span><span class="token punctuation">{</span> id<span class="token punctuation">:</span> <span class="token string">'funder1'</span><span class="token punctuation">,</span> network <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token string">'funder2'</span><span class="token punctuation">:</span> <span class="token keyword">await</span> <span class="token keyword">new</span> <span class="token class-name">httpWallet</span><span class="token punctuation">(</span><span class="token punctuation">{</span> id<span class="token punctuation">:</span> <span class="token string">'funder2'</span><span class="token punctuation">,</span> network <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">//...</span>
<span class="token punctuation">}</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><h4 id="step-2-prepare-your-coins">Step 2: Prepare Your Coins</h4><p>We have the same issue to deal with here as in step 2 in the previous example: we need to have &quot;exact change&quot; coins available for funding. The process of splitting is a little different with the wallet system though so let&#39;s walk through this version.</p>
<p>Note that the way that we&#39;re retrieving the keyring information is pretty insecure as we are sending private keys unencrypted across the network, but we&#39;ll leave for the sake of the example. <strong>DON&#39;T USE THIS IN PRODUCTION</strong>.</p>
<pre class="snippet line-numbers language-javascript"><code class="line-numbers language-javascript"><span class="token keyword">const</span> composeWalletCrowdfund <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">composeWalletCrowdfund</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment" spellcheck="true">//...</span>
<span class="token keyword">const</span> fundingCoins <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// go through each funding wallet to prepare coins</span>
<span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> id <span class="token keyword">in</span> funders<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> funder <span class="token operator">=</span> funders<span class="token punctuation">[</span>id<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> coins <span class="token operator">=</span> <span class="token keyword">await</span> funder<span class="token punctuation">.</span><span class="token function">getCoins</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> funderInfo <span class="token operator">=</span> <span class="token keyword">await</span> funder<span class="token punctuation">.</span><span class="token function">getInfo</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// Before we do anything we need to get</span>
<span class="token comment" spellcheck="true">// the fee that will be necessary for each funder's input.</span>
<span class="token keyword">const</span> funderKey <span class="token operator">=</span> <span class="token keyword">await</span> funder<span class="token punctuation">.</span><span class="token function">getWIF</span><span class="token punctuation">(</span>coins<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>address<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> funderKeyring <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">bcoin<span class="token punctuation">.</span>keyring<span class="token punctuation">.</span>fromSecret</span><span class="token punctuation">(</span>funderKey<span class="token punctuation">.</span>privateKey<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> feeForInput <span class="token operator">=</span> Utils<span class="token punctuation">.</span><span class="token function">getFeeForInput</span><span class="token punctuation">(</span>coins<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> fundeeAddress<span class="token punctuation">.</span>address<span class="token punctuation">,</span> funderKeyring<span class="token punctuation">,</span> rate<span class="token punctuation">)</span><span class="token punctuation">;</span>
amountToFund <span class="token operator">+</span><span class="token operator">=</span> feeForInput<span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// Next, go through available coins</span>
<span class="token comment" spellcheck="true">// to find a coin equal to or greater than value to fund</span>
<span class="token comment" spellcheck="true">// We didn't do this before because we knew what coins were available. But if we have one already in our wallets, then we can just use that!</span>
<span class="token keyword">let</span> fundingCoin <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> coin <span class="token keyword">of</span> coins<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>coin<span class="token punctuation">.</span>value <span class="token operator">===</span> amountToFund<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment" spellcheck="true">// if we already have a coin of the right value we can use that</span>
fundingCoin <span class="token operator">=</span> coin<span class="token punctuation">;</span>
<span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>fundingCoin<span class="token punctuation">)</span><span class="token punctuation">.</span>length<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment" spellcheck="true">// if we don't have a coin of the right amount to fund with</span>
<span class="token comment" spellcheck="true">// we need to create one by sending the funder wallet</span>
<span class="token comment" spellcheck="true">// a tx that includes an output of the right amount</span>
<span class="token comment" spellcheck="true">// this is similar to what we did in the manual version</span>
<span class="token keyword">const</span> receiveAddress <span class="token operator">=</span> <span class="token keyword">await</span> funder<span class="token punctuation">.</span><span class="token function">createAddress</span><span class="token punctuation">(</span><span class="token string">'default'</span><span class="token punctuation">)</span> <span class="token comment" spellcheck="true">// send it back to the funder</span>
<span class="token keyword">const</span> tx <span class="token operator">=</span> <span class="token keyword">await</span> funder<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
rate<span class="token punctuation">,</span>
outputs<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span>
value<span class="token punctuation">:</span> amountToFund<span class="token punctuation">,</span>
address<span class="token punctuation">:</span> receiveAddress<span class="token punctuation">.</span>address
<span class="token punctuation">}</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// get index of ouput for fundingCoin</span>
<span class="token keyword">let</span> coinIndex<span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> tx<span class="token punctuation">.</span>outputs<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>tx<span class="token punctuation">.</span>outputs<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>value <span class="token operator">===</span> amountToFund<span class="token punctuation">)</span> <span class="token punctuation">{</span>
coinIndex <span class="token operator">=</span> i<span class="token punctuation">;</span>
<span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token function">assert</span><span class="token punctuation">(</span>tx<span class="token punctuation">.</span>outputs<span class="token punctuation">[</span>coinIndex<span class="token punctuation">]</span><span class="token punctuation">.</span>value <span class="token operator">===</span> amountToFund<span class="token punctuation">,</span> <span class="token string">'value of output at index not correct'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// first argument is for the account</span>
<span class="token comment" spellcheck="true">// default is being used for all examples</span>
fundingCoin <span class="token operator">=</span> <span class="token keyword">await</span> funder<span class="token punctuation">.</span><span class="token function">getCoin</span><span class="token punctuation">(</span><span class="token string">'default'</span><span class="token punctuation">,</span> tx<span class="token punctuation">.</span>hash<span class="token punctuation">,</span> coinIndex<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
fundingCoins<span class="token punctuation">[</span>funder<span class="token punctuation">.</span>id<span class="token punctuation">]</span> <span class="token operator">=</span> fundingCoin<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><p>We now should have an object available that has the information of the coins we will be using to fund our transaction with mapped to the name of each wallet (so we can retrieve the wallet information later). It should look something like this (note that the values are larger than our funding amount due to the fee):</p>
<pre class="snippet line-numbers language-json"><code class="line-numbers language-json"><span class="token punctuation">{</span>
<span class="token property">"funder1"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"version"</span><span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
<span class="token property">"height"</span><span class="token operator">:</span> -<span class="token number">1</span><span class="token punctuation">,</span>
<span class="token property">"value"</span><span class="token operator">:</span> <span class="token number">50002370</span><span class="token punctuation">,</span>
<span class="token property">"script"</span><span class="token operator">:</span> <span class="token string">"76a914127cb1a40212169c49fe22d13307b18af1fa07ad88ac"</span><span class="token punctuation">,</span>
<span class="token property">"address"</span><span class="token operator">:</span> <span class="token string">"SNykaBMuTyeUQkK8exZyymWNrnYX5vVPuY"</span><span class="token punctuation">,</span>
<span class="token property">"coinbase"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
<span class="token property">"hash"</span><span class="token operator">:</span> <span class="token string">"163068016a39e2d9c869bcdb8646dbca93e07824db39217b5c444e7c61d1a82c"</span><span class="token punctuation">,</span>
<span class="token property">"index"</span><span class="token operator">:</span> <span class="token number">0</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token property">"funder2"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"version"</span><span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
<span class="token property">"height"</span><span class="token operator">:</span> -<span class="token number">1</span><span class="token punctuation">,</span>
<span class="token property">"value"</span><span class="token operator">:</span> <span class="token number">50002370</span><span class="token punctuation">,</span>
<span class="token property">"script"</span><span class="token operator">:</span> <span class="token string">"76a9146e08c73b355e690ba0b1198d578c4c6c52b3813688ac"</span><span class="token punctuation">,</span>
<span class="token property">"address"</span><span class="token operator">:</span> <span class="token string">"SXKossD65D7h62fhzGrntERBrPeXUfiC92"</span><span class="token punctuation">,</span>
<span class="token property">"coinbase"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
<span class="token property">"hash"</span><span class="token operator">:</span> <span class="token string">"11f3180c5069f2692f1ee1463257b21dc217441e792493c8f5ee230c35d97d96"</span><span class="token punctuation">,</span>
<span class="token property">"index"</span><span class="token operator">:</span> <span class="token number">0</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><h4 id="step-3-create-our-crowdfund-tx">Step 3: Create our Crowdfund Tx</h4><p>Now that we have our coins ready we can start to template the transaction!</p>
<p>Please note again that the way we are funding the transactions is by sending our private keys unencrypted across the network so don&#39;t use this in production.</p>
<pre class="snippet line-numbers language-javascript"><code class="line-numbers language-javascript"><span class="token keyword">const</span> composeWalletCrowdfund <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">composeWalletCrowdfund</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment" spellcheck="true">//...</span>
<span class="token keyword">const</span> fundMe <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MTX</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// Use the maxFee to calculate output value for transaction</span>
fundMe<span class="token punctuation">.</span><span class="token function">addOutput</span><span class="token punctuation">(</span><span class="token punctuation">{</span>value<span class="token punctuation">:</span> fundingTarget<span class="token punctuation">,</span> address<span class="token punctuation">:</span> fundeeAddress<span class="token punctuation">.</span>address <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// go through our coins and add each as an input in our transaction</span>
<span class="token keyword">let</span> inputCounter <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> funder <span class="token keyword">in</span> fundingCoins<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> wallet <span class="token operator">=</span> funders<span class="token punctuation">[</span>funder<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> coinOptions <span class="token operator">=</span> fundingCoins<span class="token punctuation">[</span>funder<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> key <span class="token operator">=</span> <span class="token keyword">await</span> wallet<span class="token punctuation">.</span><span class="token function">getWIF</span><span class="token punctuation">(</span>coinOptions<span class="token punctuation">.</span>address<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> keyring <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">bcoin<span class="token punctuation">.</span>keyring<span class="token punctuation">.</span>fromSecret</span><span class="token punctuation">(</span>key<span class="token punctuation">.</span>privateKey<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// this is the same utility as we used in our other example</span>
<span class="token function">addInput</span><span class="token punctuation">(</span>coinOptions<span class="token punctuation">,</span> inputCounter<span class="token punctuation">,</span> fundMe<span class="token punctuation">,</span> keyring<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">assert</span><span class="token punctuation">(</span>fundMe<span class="token punctuation">.</span><span class="token function">isSigned</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'Input has not been signed correctly'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
inputCounter<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment" spellcheck="true">// confirm that the transaction has been properly templated and signed</span>
<span class="token function">assert</span><span class="token punctuation">(</span>
fundMe<span class="token punctuation">.</span>inputs<span class="token punctuation">.</span>length <span class="token operator">===</span> Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>funders<span class="token punctuation">)</span><span class="token punctuation">.</span>length<span class="token punctuation">,</span>
<span class="token string">'Number of inputs in MTX is incorrect'</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">assert</span><span class="token punctuation">(</span>fundMe<span class="token punctuation">.</span><span class="token function">verify</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'MTX is malformed'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// make our transaction immutable so we can send it to th enetwork</span>
<span class="token keyword">const</span> tx <span class="token operator">=</span> fundMe<span class="token punctuation">.</span><span class="token function">toTX</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">assert</span><span class="token punctuation">(</span>tx<span class="token punctuation">.</span><span class="token function">verify</span><span class="token punctuation">(</span>fundMe<span class="token punctuation">.</span>view<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'TX is malformed. Fix before broadcasting'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// check the value of our inputs just to confirm what the fees are</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Total value of inputs: '</span><span class="token punctuation">,</span> fundMe<span class="token punctuation">.</span><span class="token function">getInputValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Fee to go to miners: '</span><span class="token punctuation">,</span> fundMe<span class="token punctuation">.</span><span class="token function">getInputValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span> fundingTarget<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// Finally, broadcast tx</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> broadcastStatus <span class="token operator">=</span> <span class="token keyword">await</span> client<span class="token punctuation">.</span><span class="token function">broadcast</span><span class="token punctuation">(</span>tx<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> tx<span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'There was a problem: '</span><span class="token punctuation">,</span> e<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token function">composeWalletCrowdfund</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span>myCrowdfundTx <span class="token operator">=</span><span class="token operator">></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Transaction broadcast: '</span><span class="token punctuation">,</span> myCrowdfundTx<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token keyword">catch</span><span class="token punctuation">(</span>e <span class="token operator">=</span><span class="token operator">></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'There was a problem: '</span><span class="token punctuation">,</span> e<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><p>And there you have it! If you were doing this on testnet, your <code>fundeeWallet</code> should now be 1BTC richer. If you&#39;re on a simnet or regtest network, you&#39;ll have to mine a block with your transactions to get those funds confirmed. Also note that, unless you have exact change coins, there will be 3 transactions that need to be confirmed: one each for the wallets that are splitting coins, and one for the crowdfund transaction.</p>
<h2 id="how-to-build-it-out">How to Build it Out</h2><p>These examples are obviously pretty basic, but they should give you an idea of how to use Bitcoin&#39;s scripting to build out the foundation for more complex applications. Here are some ideas on how you could build on top of these examples and get closer to a production ready application.</p>
<ul>
<li>More flexible contribution scheme (currently it&#39;s just 2 funders that split the amount evenly). E.g. custom number of contributers, custom contribution amount, etc.</li>
<li>UX to let people interact with the transaction via a browser</li>
<li>More advanced interface for fee estimation and include platform for large number of funders (for example, since you may be limited to number of funders per tx, you could include interface for multiple transactions for a single campaign. You would also want to include a check to make sure your tx is not bigger than 100kb otherwise it&#39;ll get rejected by the network)</li>
<li>Add a fund matching scheme where someone can say they will match future contributions</li>
<li>Currently the examples split transactions to make a coin available that equals the target contribution amount. This is expensive since you have to broadcast multiple transactions. An interface to choose to donate from available available coins might help to make this more efficient.</li>
</ul>
<p>Make sure to get in touch with us on Twitter or Slack if you build out any of these ideas!</p>
<p>Again, for a working example of the code (without all the text and explanations), check out <a href="https://github.com/Bucko13/bitcoin-fundraise">the repo on github</a>.</p>
<!-- END OF GUIDE -->
</div>
</div>
</div>
</div>
</article>
<!-- END OF ARTICLE CONTAINER -->
</div>
<!-- END BLOG CONTENT -->
</div><!-- .row -->
</div>
</section>
<!-- END NEW BLOGS -->
</div><!-- .row -->
</div>
</section>
<!-- END BLOGS -->
<!-- PARALLAX DOCS CTA -->
<section class="module bg-white-alfa-30 parallax color-white" data-background="../assets/images/bg-header.jpg">
<div class="container">
<div class="row">
<div class="col-sm-12">
<div class="text-center">
<h2 class="montserrat text-uppercase m-b-30">Ready to start building? Read the docs!</h2>
<a href="http://bcoin.io/docs/index.html" target="_blank" class="btn btn-lg btn-purple">Documentation</a>
</div>
</div>
</div><!-- .row -->
</div>
</section>
<!-- END PARALLAX DOCS CTA -->
<!-- FOOTER -->
<footer id="footer" class="footer-minimal">
<div class="container">
<div class="row">
<div class="col-sm-12">
<ul class="social-icons social-icons-circle text-center m-b-35">
<li><a href="https://twitter.com/bcoin"><i class="fa fa-twitter"></i></a></li>
<li><a href="https://github.com/bcoin-org/bcoin"><i class="fa fa-github"></i></a></li>
<li><a href="../slack-signup.html" target="_blank"><i class="fa fa-slack"></i></a></li>
</ul>
</div>
</div>
<div class="row">
<div class="col-sm-12 text-center m-b-35">
<img class="m-b-35 QR-code" src="../assets/images/donation_QR.png"/>
<p class="m-0"><strong>Bcoin Development Donation Address:</strong><br />3Bi9H1hzCHWJoFEjc4xzVzEMywi35dyvsV</p>
</div>
</div>
<div class="row">
<div class="col-sm-12 text-center">
<p class="m-0">Copyright <a href="#">bcoin.io, Purse</a>, 2017, All Rights Reserved.</p>
</div>
</div>
</div>
</footer>
<!-- END FOOTER -->
</div>
<!-- /WRAPPER -->
<!-- JAVASCRIPT FILES -->
<script src="../assets/js/jquery-2.2.3.min.js"></script>
<script src="http://maps.googleapis.com/maps/api/js?v=3"></script>
<script src="../assets/bootstrap/js/bootstrap.min.js"></script>
<script src="../assets/js/plugins.min.js"></script>
<script src="../assets/js/stickyfill.min.js"></script>
<script src="../assets/js/custom.min.js"></script>
<script src="../assets/js/clipboard.min.js"></script>
<script async defer src="../assets/js/prism.js"></script>
<script>
var copyCode = new Clipboard('.copy-button', {
target: function(trigger) {
return trigger.previousElementSibling;
}
});
copyCode.on('success', function(event) {
event.trigger.classList.add('success');
event.clearSelection();
// event.trigger.textContent = 'Copied!';
window.setTimeout(function() {
event.trigger.classList.remove('success');
}, 2000);
});
</script>
<!-- github button js -->
<script async defer src="https://buttons.github.io/buttons.js"></script>
</body>
</html>

3
guides/generate-address.html

@ -267,9 +267,10 @@
<ul class="icons-list">
<!-- GUIDES-LIST -->
<li><a href="scripting.html">Intro to Scripting</a></li>
<li><a href="op_return.html">Create an OP_RETURN output transaction</a></li>
<li><a href="op_return.html">Store Data on the Blockchain</a></li>
<li><a href="multisig-tx.html">Creating Multi Signature Transactions</a></li>
<li><a href="generate-address.html">Generate an Address</a></li>
<li><a href="crowdfund-tx.html">Create a Crowdfunding Transaction</a></li>
<!-- /GUIDES-LIST -->
</ul>
</div>

3
guides/install-linux.html

@ -267,9 +267,10 @@
<ul class="icons-list">
<!-- GUIDES-LIST -->
<li><a href="scripting.html">Intro to Scripting</a></li>
<li><a href="op_return.html">Create an OP_RETURN output transaction</a></li>
<li><a href="op_return.html">Store Data on the Blockchain</a></li>
<li><a href="multisig-tx.html">Creating Multi Signature Transactions</a></li>
<li><a href="generate-address.html">Generate an Address</a></li>
<li><a href="crowdfund-tx.html">Create a Crowdfunding Transaction</a></li>
<!-- /GUIDES-LIST -->
</ul>
</div>

3
guides/install-mac.html

@ -267,9 +267,10 @@
<ul class="icons-list">
<!-- GUIDES-LIST -->
<li><a href="scripting.html">Intro to Scripting</a></li>
<li><a href="op_return.html">Create an OP_RETURN output transaction</a></li>
<li><a href="op_return.html">Store Data on the Blockchain</a></li>
<li><a href="multisig-tx.html">Creating Multi Signature Transactions</a></li>
<li><a href="generate-address.html">Generate an Address</a></li>
<li><a href="crowdfund-tx.html">Create a Crowdfunding Transaction</a></li>
<!-- /GUIDES-LIST -->
</ul>
</div>

3
guides/install-windows.html

@ -267,9 +267,10 @@
<ul class="icons-list">
<!-- GUIDES-LIST -->
<li><a href="scripting.html">Intro to Scripting</a></li>
<li><a href="op_return.html">Create an OP_RETURN output transaction</a></li>
<li><a href="op_return.html">Store Data on the Blockchain</a></li>
<li><a href="multisig-tx.html">Creating Multi Signature Transactions</a></li>
<li><a href="generate-address.html">Generate an Address</a></li>
<li><a href="crowdfund-tx.html">Create a Crowdfunding Transaction</a></li>
<!-- /GUIDES-LIST -->
</ul>
</div>

46
guides/multisig-tx.html

@ -267,9 +267,10 @@
<ul class="icons-list">
<!-- GUIDES-LIST -->
<li><a href="scripting.html">Intro to Scripting</a></li>
<li><a href="op_return.html">Create an OP_RETURN output transaction</a></li>
<li><a href="op_return.html">Store Data on the Blockchain</a></li>
<li><a href="multisig-tx.html">Creating Multi Signature Transactions</a></li>
<li><a href="generate-address.html">Generate an Address</a></li>
<li><a href="crowdfund-tx.html">Create a Crowdfunding Transaction</a></li>
<!-- /GUIDES-LIST -->
</ul>
</div>
@ -324,21 +325,22 @@ signatories chooses a different <code>m</code> or a different <code>n</code>, th
You also need to know the pubkey for all cosigners.
You can share these pubkeys however you want. Wallets support various ways for sharing pubkeys, using QR Codes
or sending base58check encoded strings. After you have collected all pubkeys and agreed on <code>m</code> and <code>n</code>,
you construct the multisig script and generate P2SH address from that. </p>
you construct the multisig script and generate P2SH address from that.</p>
<h4 id="spending-received-transaction">Spending Received Transaction</h4><p>After you&#39;ve received a transaction on your multisig address, you can spend it if the minimum number of signatures are provided
in a signature script. </p>
in a signature script.</p>
<ol>
<li>You need all public keys, the same as were used in address generation. </li>
<li>From that you can construct the redeem script, that is the original script you constructed for address. </li>
<li>You need all public keys, the same as were used in address generation.</li>
<li>From that you can construct the redeem script, that is the original script you constructed for address.</li>
<li>Once you have the redeem script, you can start creating the signature script which will be constructed according
to BIP11 and BIP16. </li>
to BIP11 and BIP16.</li>
<li>When you prepend your signature, you take this transaction (not yet fully valid) and send it to another pubkey owner,
who&#39;ll be signing next. The next person will do the same, until you have <code>m</code> signatures in the sigscript.</li>
</ol>
<p>After this process is done, your transaction is fully signed and you can broadcast your transaction.</p>
<h2 id="the-code">The Code</h2><h3 id="manual-construction">Manual construction</h3><p>In this setup, we won&#39;t be running a node or running any of the blockchain or wallet functionality of bcoin.
This is a slightly more abstract than constructing bare scripts ourselves.<br>We&#39;ll split code in multiple files and share keys using the current directory (So you can use fresh dir).</p>
<h3 id="step-1:-address-creation">Step 1: Address Creation</h3><p>In the following code, we&#39;ll import all necessary libraries, generate private and public keys, and create
This is a slightly more abstract than constructing bare scripts ourselves.
We&#39;ll split code in multiple files and share keys using the current directory (So you can use fresh dir).</p>
<h3 id="step-1-address-creation">Step 1: Address Creation</h3><p>In the following code, we&#39;ll import all necessary libraries, generate private and public keys, and create
a multisig address.</p>
<pre class="snippet line-numbers language-js"><code class="line-numbers language-js"><span class="token string">'use strict'</span><span class="token punctuation">;</span>
@ -384,7 +386,7 @@ console<span class="token punctuation">.</span><span class="token function">log<
<pre class="snippet line-numbers language-js"><code class="line-numbers language-js"><span class="token keyword">const</span> ring1 <span class="token operator">=</span> KeyRing<span class="token punctuation">.</span><span class="token function">generate</span><span class="token punctuation">(</span>compressed<span class="token punctuation">,</span> network<span class="token punctuation">)</span><span class="token punctuation">;</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><p>Here we generate a private key and public key pair. We need to provide
information about the network and public key format. There are two <a href="https://bitcoin.org/en/developer-guide#public-key-formats">Public key formats</a>
one compressed and one uncompressed. More details can be found at the <a href="https://bitcoin.org/en/developer-guide#public-key-formats">Bitcoin Developer Guide</a></p>
<h3 id="step-2:-generate-transaction">Step 2: Generate Transaction</h3><p>In this part, we assume that we received a transaction on the network with the following information:</p>
<h3 id="step-2-generate-transaction">Step 2: Generate Transaction</h3><p>In this part, we assume that we received a transaction on the network with the following information:</p>
<blockquote>
<p>Transaction ID: 3b1dd17cc82e2ac43ba62bf8f1c6a0fe805df43911653d22c902571eb3a212ce<br>Output index: 0<br>Amount: 100 BTC </p>
</blockquote>
@ -513,11 +515,11 @@ spend2<span class="token punctuation">.</span><span class="token function">signI
<span class="token comment" spellcheck="true">// Let's make sure that the transaction is valid</span>
<span class="token function">assert</span><span class="token punctuation">(</span>spend2<span class="token punctuation">.</span><span class="token function">verify</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'Transaction isnt valid.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>spend2<span class="token punctuation">.</span><span class="token function">toRaw</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token string">'hex'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><p>Since there&#39;s a lot of code here, I wanted to review a couple of sections.
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>spend2<span class="token punctuation">.</span><span class="token function">toRaw</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token string">'hex'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><p>Since there&#39;s a lot of code here, I wanted to review a couple of sections.
This snippet below will return a raw transaction and also makes sure the
transaction has all the signatures.</p>
<hr>
<pre class="snippet line-numbers language-js"><code class="line-numbers language-js"><span class="token comment" spellcheck="true">// send change to ourselves </span>
<pre class="snippet line-numbers language-js"><code class="line-numbers language-js"><span class="token comment" spellcheck="true">// send change to ourselves</span>
spend1<span class="token punctuation">.</span><span class="token function">addOutput</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
address<span class="token punctuation">:</span> changeAddr<span class="token punctuation">,</span>
value<span class="token punctuation">:</span> Amount<span class="token punctuation">.</span><span class="token function">fromBTC</span><span class="token punctuation">(</span><span class="token string">'49.99'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
@ -529,7 +531,8 @@ spend1<span class="token punctuation">.</span><span class="token function">addOu
spend1<span class="token punctuation">.</span><span class="token function">addCoin</span><span class="token punctuation">(</span>coin<span class="token punctuation">)</span><span class="token punctuation">;</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><p>In this next snippet we send change to ourselves and specify it manually.
Alternatively, we could also use <code>MTX.prototype.fund</code> which automatically
allocates coins to outputs, based on the amounts they need and
also calculate change and append a new output for it.<br>Instead of the code above, we could have simpler and more automated</p>
also calculate change and append a new output for it.
Instead of the code above, we could have simpler and more automated</p>
<p>calculations:</p>
<pre class="snippet line-numbers language-js"><code class="line-numbers language-js"><span class="token comment" spellcheck="true">// this will automatically select coins and</span>
<span class="token comment" spellcheck="true">// send change back to our address</span>
@ -541,7 +544,7 @@ also calculate change and append a new output for it.<br>Instead of the code abo
convenient to handle all logic manually, and even more complex to deal with all HD wallet logic. So if you have a bcoin node running and you have access to it via HTTP, you can use <code>bcoin.http.Client</code> and <code>bcoin.http.Wallet</code>. These classes
provide all API methods described on bcoin and will communicate with the node&#39;s Wallets.</p>
<p><em>NOTE: You can check <a href="http://bcoin.io/api-docs/index.html">API Docs</a></em></p>
<h3 id="step-1:-address-creation">Step 1: Address Creation</h3><p>In this step we&#39;ll create two new wallets for two cosigners. In this demo, they will exist on same node,
<h3 id="step-1-address-creation">Step 1: Address Creation</h3><p>In this step we&#39;ll create two new wallets for two cosigners. In this demo, they will exist on same node,
but it shouldn&#39;t matter if these two wallets are on the same node or not.</p>
<pre class="snippet line-numbers language-js"><code class="line-numbers language-js"><span class="token string">'use strict'</span><span class="token punctuation">;</span>
@ -654,11 +657,12 @@ but it shouldn&#39;t matter if these two wallets are on the same node or not.</p
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><p>You will notice that we grab the <code>.account.accountKey</code>, first key is the xpubkey
and both will be using xpubkey key derivation to come up with new addresses.
You won&#39;t need to share any other public keys, they will derive them for you.
Depth of the account is the only thing you&#39;ll need to keep in mind.<br><a href="http://bcoin.io/api-docs/index.html#add-xpubkey-multisig">addSharedKey</a> in
Depth of the account is the only thing you&#39;ll need to keep in mind.
<a href="http://bcoin.io/api-docs/index.html#add-xpubkey-multisig">addSharedKey</a> in
wallet/account is used for adding cosigner xpubkeys keys.</p>
<h3 id="step-2:-generate-transaction">Step 2: Generate Transaction</h3><p>We have received transaction</p>
<h3 id="step-2-generate-transaction">Step 2: Generate Transaction</h3><p>We have received transaction</p>
<blockquote>
<p>Transaction ID: 3c12e1b260354fd2a2848030222c4a66339892f1d63b18752ff80ef4eb0197d2<br>Output index: 0<br>Amount: 100 BTC </p>
<p>Transaction ID: c12e1b260354fd2a2848030222c4a66339892f1d63b18752ff80ef4eb0197d2<br>Output index: 0<br>Amount: 100 BTC </p>
</blockquote>
<p>We are going to send <code>1 BTC</code> to <code>RBg1TLaNuRpH6UTFzogFXhjqubPYZaqWgs</code> on the regtest network.</p>
<p>We won&#39;t need transaction ID and output index when using wallet API. It will be automatically
@ -679,7 +683,7 @@ allocated from coins by bcoin node wallet service.</p>
<span class="token comment" spellcheck="true">// Because we can't sign and spend from account</span>
<span class="token comment" spellcheck="true">// We can't use `spend` as we do with normal transactions</span>
<span class="token comment" spellcheck="true">// since it immediately publishes to the network </span>
<span class="token comment" spellcheck="true">// since it immediately publishes to the network</span>
<span class="token comment" spellcheck="true">// and we need other signatures first.</span>
<span class="token comment" spellcheck="true">// So we first create the transaction</span>
<span class="token keyword">const</span> outputs <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> address<span class="token punctuation">:</span> sendTo<span class="token punctuation">,</span> value<span class="token punctuation">:</span> Amount<span class="token punctuation">.</span><span class="token function">fromBTC</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
@ -692,7 +696,7 @@ allocated from coins by bcoin node wallet service.</p>
<span class="token comment" spellcheck="true">// also create changeAddress and calculate fee</span>
<span class="token keyword">const</span> tx1 <span class="token operator">=</span> <span class="token keyword">await</span> wallet1<span class="token punctuation">.</span><span class="token function">createTX</span><span class="token punctuation">(</span>options<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// Now you can share this raw output </span>
<span class="token comment" spellcheck="true">// Now you can share this raw output</span>
<span class="token keyword">const</span> raw <span class="token operator">=</span> tx1<span class="token punctuation">.</span>hex<span class="token punctuation">;</span>
<span class="token comment" spellcheck="true">// Wallet2 will also sign the transaction</span>
@ -704,7 +708,7 @@ allocated from coins by bcoin node wallet service.</p>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token keyword">catch</span><span class="token punctuation">(</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">></span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">;</span>
process<span class="token punctuation">.</span><span class="token function">exit</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><p>Here you can see it&#39;s much cleaner and easier.
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code><button class="copy-button"><img src="../assets/images/clippy.svg" alt="Copy to clipboard"></button></pre><p>Here you can see it&#39;s much cleaner and easier.
We still need to manually, using other means, share
raw transaction data for signing.</p>
<p><code>wallet1.createTX(options)</code> will automatically find the coins
@ -712,8 +716,8 @@ sent to the multisig wallet, allocate them for spending,
send remaining funds (minus fee) to change address and sign it.</p>
<p><code>wallet2.sign</code> will take raw transaction and sign it with according key.
After that we can just broadcast the transaction to the network.</p>
<h2 id="final-notes">Final Notes</h2><p>I hope, this guide gives you opportunity to understand multisig transactions better and build apps on top of it.
You can play with this code and even build use it in production with small changes (e.g. rate estimation).</p>
<h2 id="final-notes">Final Notes</h2><p>I hope this guide gives you the opportunity to better understand multisig transactions and build apps on top of it.</p>
<p>You can play with this code, extend it, and even use it in production with small changes (e.g. rate estimation).</p>
<p>Here are some other ideas for how to build out on top of the app we built in this guide:</p>
<ul>
<li>Build UI for configuring and initializing <code>m</code> and <code>n</code>.</li>

5
guides/op_return.html

@ -267,9 +267,10 @@
<ul class="icons-list">
<!-- GUIDES-LIST -->
<li><a href="scripting.html">Intro to Scripting</a></li>
<li><a href="op_return.html">Create an OP_RETURN output transaction</a></li>
<li><a href="op_return.html">Store Data on the Blockchain</a></li>
<li><a href="multisig-tx.html">Creating Multi Signature Transactions</a></li>
<li><a href="generate-address.html">Generate an Address</a></li>
<li><a href="crowdfund-tx.html">Create a Crowdfunding Transaction</a></li>
<!-- /GUIDES-LIST -->
</ul>
</div>
@ -307,7 +308,7 @@
<div class="col-sm-12 panel panel-default">
<div class="post-content" style="color:#000;">
<!-- START OF GUIDE -->
<h2 class="post-title panel-title" id="create-an-op_return-output-transaction">Create an OP_RETURN output transaction</h2><ul class="post-meta"><li class="author">By Javed Khan</li></ul><p>OP_RETURN is a script opcode which can be used to store an arbitrary 40-byte
<h2 class="post-title panel-title" id="store-data-on-the-blockchain">Store Data on the Blockchain</h2><ul class="post-meta"><li class="author">By Javed Khan</li></ul><h2 id="opreturn-script-opcode">OP_RETURN Script Opcode</h2><p>OP_RETURN is a script opcode which can be used to store an arbitrary 40-byte
data as a part of the signature script (null data script), allowing one to
embed a small amount of data into the blockchain. For example, it can be used
as a way to track digital assets or certify a document with proof-of-existence.

3
guides/scripting.html

@ -267,9 +267,10 @@
<ul class="icons-list">
<!-- GUIDES-LIST -->
<li><a href="scripting.html">Intro to Scripting</a></li>
<li><a href="op_return.html">Create an OP_RETURN output transaction</a></li>
<li><a href="op_return.html">Store Data on the Blockchain</a></li>
<li><a href="multisig-tx.html">Creating Multi Signature Transactions</a></li>
<li><a href="generate-address.html">Generate an Address</a></li>
<li><a href="crowdfund-tx.html">Create a Crowdfunding Transaction</a></li>
<!-- /GUIDES-LIST -->
</ul>
</div>

2
utils/createHTML.js

@ -25,7 +25,7 @@ const createHTML = async function createHTML(markdownFile, htmlFile, author, pos
// Custom renderer for top two level headers
renderer.heading = (text, level) => {
let textURL = text.replace(/\(.+\)/, '').trim(); // for url remove any parentheses and their contents
textURL = textURL.replace(/ /g, '-').toLowerCase(); // and replace spaces with dashes
textURL = textURL.replace(/[$-/:-?{-~!"^_`\[\]]/, '').replace(/ /g, '-').toLowerCase(); // and replace spaces with dashes
if (level == '1' ) {
// remove icon tag for the url

Loading…
Cancel
Save