From 32f8360fd54022bc0b2b25a2952f4a0dab5ec3a1 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Tue, 16 Dec 2014 02:59:02 -0300 Subject: [PATCH] Update Networks, PrivateKey and Script --- docs/Networks.md | 45 ++++++++++++++------- docs/Opcode.md | 1 - docs/PrivateKey.md | 12 ++---- docs/Script.md | 97 ++++++++++++++++------------------------------ 4 files changed, 67 insertions(+), 88 deletions(-) delete mode 100644 docs/Opcode.md diff --git a/docs/Networks.md b/docs/Networks.md index 40dff2c..96fffd9 100644 --- a/docs/Networks.md +++ b/docs/Networks.md @@ -1,23 +1,40 @@ # Networks -Bitcore provides support for both the main bitcoin network as well as for -`testnet3`, the current test blockchain. We encourage the use of -`Networks.livenet` and `Networks.testnet` as constants. Note that the library -sometimes may check for equality against this object. Avoid creating a deep -copy of this object and using that. +Bitcore provides support for both the main bitcoin network as well as for `testnet3`, the current test blockchain. We encourage the use of `Networks.livenet` and `Networks.testnet` as constants. Note that the library sometimes may check for equality against this object. Avoid creating a deep copy of this object and using that. + +The `Network` namespace has a function, `get(...)` that returns an instance of a `Network` or `undefined`. The only argument to this function is some kind of identifier of the network: either its name, a reference to a Network object, or a number used as a magic constant to identify the network (for example, the value `0` that gives bitcoin addresses the distinctive `'1'` at its beginning on livenet, is a `0x6F` for testnet). ## Setting the default network -Most project will only need to work in one of either networks. The value of -`Networks.defaultNetwork` can be set to `Networks.testnet` if the project will -needs only to work on testnet (the default is `Networks.livenet`). +Most project will only need to work in one of either networks. The value of `Networks.defaultNetwork` can be set to `Networks.testnet` if the project will needs only to work on testnet (the default is `Networks.livenet`). ## Network constants -The functionality of testnet and livenet is mostly similar (except for some -relaxed block validation rules on testnet). They differ in the constants being -used for human representation of base58 encoded strings. These are sometimes -referred to as "version" constants. +The functionality of testnet and livenet is mostly similar (except for some relaxed block validation rules on testnet). They differ in the constants being used for human representation of base58 encoded strings. These are sometimes referred to as "version" constants. -## Source -TODO: Include source here +Take a look at this modified snippet from (networks.js)[https://github.com/bitpay/bitcore/blob/master/lib/networks.js] +```javascript +var livenet = new Network(); +_.extend(livenet, { + name: 'livenet', + alias: 'mainnet', + pubkeyhash: 0x00, + privatekey: 0x80, + scripthash: 0x05, + xpubkey: 0x0488b21e, + xprivkey: 0x0488ade4, + port: 8333 +}); + +var testnet = new Network(); +_.extend(testnet, { + name: 'testnet', + alias: 'testnet', + pubkeyhash: 0x6f, + privatekey: 0xef, + scripthash: 0xc4, + xpubkey: 0x043587cf, + xprivkey: 0x04358394, + port: 18333 +}); +``` diff --git a/docs/Opcode.md b/docs/Opcode.md deleted file mode 100644 index 713d29c..0000000 --- a/docs/Opcode.md +++ /dev/null @@ -1 +0,0 @@ -# Opcode diff --git a/docs/PrivateKey.md b/docs/PrivateKey.md index 4b6cf7b..4465ffa 100644 --- a/docs/PrivateKey.md +++ b/docs/PrivateKey.md @@ -7,22 +7,20 @@ Represents a bitcoin private key and is needed to be able to spend bitcoin and s Here is how to create a new private key. It will generate a new random number using `window.crypto` or the Node.js 'crypto' library. ```javascript - -var PrivateKey = require('bitcore/lib/privatekey'); var privateKey = new PrivateKey(); +// Creates a private key from a hexa encoded number +var privateKey2 = new PrivateKey('b221d9dbb083a7f33428d7c2a3c3198ae925614d70210e28716ccaa7cd4ddb79'); ``` To export and import a private key, you can do the following: ```javascript - // encode into wallet export format var exported = privateKey.toWIF(); // instantiate from the exported (and saved) private key var imported = PrivateKey.fromWIF('L3T1s1TYP9oyhHpXgkyLoJFGniEgkv2Jhi138d7R2yJ9F4QdDU2m'); - ``` Note: The WIF (Wallet Import Format) includes information about the network and if the associated public key is compressed or uncompressed (thus the same bitcoin address will be generated by using this format). @@ -30,10 +28,8 @@ Note: The WIF (Wallet Import Format) includes information about the network and To generate an Address or PublicKey from a PrivateKey: ```javascript - -var address = privateKey.toAddress(); var publicKey = privateKey.toPublicKey(); - +var address = publicKey.toAddress(Networks.livenet); ``` ## Validating a Private Key @@ -41,7 +37,6 @@ var publicKey = privateKey.toPublicKey(); The code to do these validations looks like this: ```javascript - // validate an address if (PrivateKey.isValid(input)){ ... @@ -52,5 +47,4 @@ var error = PrivateKey.getValidationError(input, Networks.livenet); if (error) { // handle the error } - ``` diff --git a/docs/Script.md b/docs/Script.md index f2193c3..47fab72 100644 --- a/docs/Script.md +++ b/docs/Script.md @@ -1,25 +1,13 @@ # Script -All bitcoin transactions have scripts embedded into its inputs and outputs. -The scripts use a very simple programming language, which is evaluated from -left to right using a stack. The language is designed such that it guarantees -all scripts will execute in a limited amount of time (it is not Turing-Complete). +All bitcoin transactions have scripts embedded into its inputs and outputs. The scripts use a very simple programming language, which is evaluated from left to right using a stack. The language is designed such that it guarantees all scripts will execute in a limited amount of time (it is not Turing-Complete). -When a transaction is validated, the input scripts are concatenated with the output -scripts and evaluated. To be valid, all transaction scripts must evaluate to true. -A good analogy for how this works is that the output scripts are puzzles that specify -in which conditions can those bitcoins be spent. The input scripts provide the correct -data to make those output scripts evaluate to true. +When a transaction is validated, the input scripts are concatenated with the output scripts and evaluated. To be valid, all transaction scripts must evaluate to true. A good analogy for how this works is that the output scripts are puzzles that specify in which conditions can those bitcoins be spent. The input scripts provide the correct data to make those output scripts evaluate to true. -For more detailed information about the bitcoin scripting language, check the -online reference: https://en.bitcoin.it/wiki/Script - -The `Script` object provides an interface to construct, parse, and identify bitcoin -scripts. It also gives simple interfaces to create most common script types. This class -is useful if you want to create custom input or output scripts. In other case, -you should probably use `Transaction`. +For more detailed information about the bitcoin scripting language, check the online reference (on bitcoin's wiki)[https://en.bitcoin.it/wiki/Script]. +The `Script` object provides an interface to construct, parse, and identify bitcoin scripts. It also gives simple interfaces to create most common script types. This class is useful if you want to create custom input or output scripts. In other case, you should probably use `Transaction`. ## Script creation @@ -27,39 +15,30 @@ Here's how to use `Script` to create the five most common script types: ### Pay to Public Key Hash (p2pkh) -This is the most commonly used transaction output script. It's used to pay to -a bitcoin address (a bitcoin address is a public key hash encoded in base58check) +This is the most commonly used transaction output script. It's used to pay to a bitcoin address (a bitcoin address is a public key hash encoded in base58check) ```javascript // create a new p2pkh paying to a specific address var address = Address.fromString('1NaTVwXDDUJaXDQajoa9MqHhz4uTxtgK14'); -var s = Script.buildPublicKeyHashOut(address); -console.log(s.toString()); -// 'OP_DUP OP_HASH160 20 0xecae7d092947b7ee4998e254aa48900d26d2ce1d OP_EQUALVERIFY OP_CHECKSIG' +var script = Script.buildPublicKeyHashOut(address); +assert(script.toString() === 'OP_DUP OP_HASH160 20 0xecae7d092947b7ee4998e254aa48900d26d2ce1d OP_EQUALVERIFY OP_CHECKSIG'); ``` ### Pay to Public Key (p2pk) -Pay to public key scripts are a simplified form of the p2pkh, -but aren’t commonly used in new transactions anymore, because p2pkh scripts are -more secure (the public key is not revealed until the output is spent). +Pay to public key scripts are a simplified form of the p2pkh, but aren’t commonly used in new transactions anymore, because p2pkh scripts are more secure (the public key is not revealed until the output is spent). ```javascript // create a new p2pk paying to a specific public key var pubkey = new PublicKey('022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da'); -var s = Script.buildPublicKeyOut(pubkey); -console.log(s.toString()); -// '33 0x022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da OP_CHECKSIG' +var script = Script.buildPublicKeyOut(pubkey); +assert(script.toString() === '33 0x022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da OP_CHECKSIG'); ``` ### Pay to Multisig (p2ms) -Multisig outputs allow to share control of bitcoins between several keys. When creating -the script, one specifies the public keys that control the funds, and how many of those -keys are required to sign off spending transactions to be valid. An output with N public keys -of which M are required is called an m-of-n output (For example, 2-of-3, 3-of-5, 4-of-4, etc.) +Multisig outputs allow to share control of bitcoins between several keys. When creating the script, one specifies the public keys that control the funds, and how many of those keys are required to sign off spending transactions to be valid. An output with N public keys of which M are required is called an m-of-n output (For example, 2-of-3, 3-of-5, 4-of-4, etc.) -Note that regular multisig outputs are rarely used nowadays. The best practice -is to use a p2sh multisig output (See Script#toScriptHashOut()). +Note that regular multisig outputs are rarely used nowadays. The best practice is to use a p2sh multisig output (See Script#toScriptHashOut()). ```javascript // create a new 2-of-3 multisig output from 3 given public keys @@ -68,19 +47,16 @@ var pubkeys = [ new PublicKey('03e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e9'), new PublicKey('021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc18'), ]; -var m = 2; -var s = Script.buildMultisigOut(pubkeys, m); -console.log(s.toString()); -// 'OP_2 33 0x022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da 33 0x03e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e9 33 0x021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc18 OP_3 OP_CHECKMULTISIG' +var threshold = 2; +var script = Script.buildMultisigOut(pubkeys, threshold); +assert(script.toString() === 'OP_2 33 0x022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da' + + ' 33 0x03e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e9' + + ' 33 0x021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc18 OP_3 OP_CHECKMULTISIG'); ``` ### Pay to Script Hash (p2sh) -Pay to script hash outputs are scripts that contain the hash of another script, called redeemScript. -To spend bitcoins sent in a p2sh output, the spending transaction must provide a script -matching the script hash and data which makes the script evaluate to true. -This allows to defer revealing the spending conditions to the moment of spending. It also -makes it possible for the receiver to set the conditions to spend those bitcoins. +Pay to script hash outputs are scripts that contain the hash of another script, called `redeemScript`. To spend bitcoins sent in a p2sh output, the spending transaction must provide a script matching the script hash and data which makes the script evaluate to true. This allows to defer revealing the spending conditions to the moment of spending. It also makes it possible for the receiver to set the conditions to spend those bitcoins. Most multisig transactions today use p2sh outputs where the redeemScript is a multisig output. @@ -92,44 +68,38 @@ var pubkeys = [ new PublicKey('021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc18'), ]; var redeemScript = Script.buildMultisigOut(pubkeys, 2); -var s = redeemScript.toScriptHashOut(); -console.log(s.toString()); -// 'OP_HASH160 20 0x620a6eeaf538ec9eb89b6ae83f2ed8ef98566a03 OP_EQUAL' +var script = redeemScript.toScriptHashOut(); +assert(script.toString() === 'OP_HASH160 20 0x620a6eeaf538ec9eb89b6ae83f2ed8ef98566a03 OP_EQUAL'); ``` ### Data output -Data outputs are used to push data into the blockchain. Up to 40 bytes can be pushed -in a standard way, but more data can be used, if a miner decides to accept the transaction. +Data outputs are used to push data into the blockchain. Up to 40 bytes can be pushed in a standard way, but more data can be used, if a miner decides to accept the transaction. ```javascript var data = 'hello world!!!'; -var s = Script.buildDataOut(data); -console.log(s.toString()); -// 'OP_RETURN 14 0x68656c6c6f20776f726c64212121' +var script = Script.buildDataOut(data); +assert(script.toString() === 'OP_RETURN 14 0x68656c6c6f20776f726c64212121' ``` ### Custom scripts -To create a custom `Script` instance, you must rely on the lower-level methods `add` -and `prepend`. Both methods accept the same parameter types, and insert an opcode or -data at the beginning (`prepend`) or end (`add`) of the `Script`. +To create a custom `Script` instance, you must rely on the lower-level methods `add` and `prepend`. Both methods accept the same parameter types, and insert an opcode or data at the beginning (`prepend`) or end (`add`) of the `Script`. ``` -var s = Script() - .add('OP_IF') // add an opcode by name - .prepend(114) // add OP_2SWAP by code - .add(new Opcode('OP_NOT')) // add an opcode object - .add(new Buffer('bacacafe', 'hex')) // add a data buffer -console.log(s.toString()); -// 'OP_2SWAP OP_IF OP_NOT 4 0xbacacafe' +var script = Script() + .add('OP_IF') // add an opcode by name + .prepend(114) // add OP_2SWAP by code + .add(Opcode.OP_NOT) // add an opcode object + .add(new Buffer('bacacafe', 'hex')) // add a data buffer (will append the size of the push operation first) + +assert(script.toString() === 'OP_2SWAP OP_IF OP_NOT 4 0xbacacafe'); ``` ## Script parsing and identification -`Script` has an easy interface to parse raw scripts from the newtwork or bitcoind, -and to extract useful information. -An illustrative example (for more options check the API reference) +`Script` has an easy interface to parse raw scripts from the newtwork or bitcoind, and to extract useful information. An illustrative example (for more options check the API reference) + ```javascript var raw_script = new Buffer('5221022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da2103e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e921021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc1853ae', 'hex'); var s = new Script(raw_script); @@ -139,5 +109,4 @@ console.log(s.toString()); s.isPublicKeyHashOut() // false s.isScriptHashOut() // false s.isMultisigOut() // true - ```