From 63f1d307fa07f29b4941bb58537b012d686ac208 Mon Sep 17 00:00:00 2001 From: Esteban Ordano Date: Tue, 16 Dec 2014 02:45:23 -0300 Subject: [PATCH] Reviewing docs --- docs/Address.md | 36 +++++---------- docs/Block.md | 25 +---------- docs/Crypto.md | 25 +++-------- docs/Encoding.md | 13 +----- docs/Hierarchical.md | 40 ++++++++++++++--- docs/Input.md | 1 - docs/Output.md | 1 - docs/Transaction.md | 102 +++++++++++-------------------------------- lib/block.js | 25 ++++++++++- lib/blockheader.js | 4 ++ 10 files changed, 107 insertions(+), 165 deletions(-) delete mode 100644 docs/Input.md delete mode 100644 docs/Output.md diff --git a/docs/Address.md b/docs/Address.md index 09b7cbd..33ca267 100644 --- a/docs/Address.md +++ b/docs/Address.md @@ -1,57 +1,40 @@ # Address -Represents a bitcoin Address. Addresses became the most popular way to make -bitcoin transactions. See [the official Bitcoin -Wiki](https://en.bitcoin.it/wiki/Address) for more information. - +Represents a bitcoin Address. Addresses became the most popular way to make bitcoin transactions. See [the official Bitcoin Wiki](https://en.bitcoin.it/wiki/Address) for more information. ## Instantiate an Address -To be able to receive bitcoin an address is needed, here is how to create an -address from a new private key. Please see the [`PrivateKey`](PrivateKey.md) docs -for more information about exporting and saving a key. +To be able to receive bitcoins an address is needed, but in order to spend them a private key is necessary. Take a look at the [`PrivateKey`](PrivateKey.md) docs for more information about exporting and saving a key. ```javascript - -var PrivateKey = require('bitcore/lib/privatekey'); var privateKey = new PrivateKey(); var address = privateKey.toAddress(); - ``` -You can also instantiate an address from a String or PublicKey. +You can also instantiate an address from a String, `PublicKey`, or [HDPublicKey](Hierarchical.md), in case you are not the owner of the private key. ```javascript - -var Address = require('bitcore/lib/address'); -var PublicKey = require('bitcore/lib/publickey'); -var Networks = require('bitcore/lib/networks'); - // from a string var address = Address.fromString('mwkXG8NnB2snbqWTcpNiK6qqGHm1LebHDc'); // a default network address from a public key var publicKey = PublicKey(privateKey); +var address = new Address(publicKey); +// alternative interface var address = Address.fromPublicKey(publicKey); // a testnet address from a public key -var publicKey = PublicKey(privateKey); -var address = Address.fromPublicKey(publicKey, Networks.testnet); - +var publicKey = new PublicKey(privateKey); +var address = new Address(publicKey, Networks.testnet); ``` ## Validating an Address -The main use that we expect you'll have for the `Address` class in bitcore is -validating that an address is a valid one, what type of address it is (you may -be interested on knowning if the address is a simple "pay to public key hash" -address or a "pay to script hash" address) and what network does the address -belong to. +The main use that we expect you'll have for the `Address` class in bitcore is validating that an address is a valid one, what type of address it is (you may be interested on knowing if the address is a simple "pay to public key hash" address or a "pay to script hash" address) and what network does the address belong to. The code to do these validations looks like this: ```javascript - // validate an address if (Address.isValid(input){ ... @@ -73,5 +56,6 @@ var error = Address.getValidationError(input, Networks.testnet); // handle the error } } - ``` + +The errors are listed in the generated file in the [errors folder](https://github.com/bitpay/bitcore/tree/master/lib/errors). There's a structure to errors defined in the [spec.js file](https://github.com/bitpay/bitcore/tree/master/lib/errors/spec.js). diff --git a/docs/Block.md b/docs/Block.md index b35642e..1016db4 100644 --- a/docs/Block.md +++ b/docs/Block.md @@ -1,15 +1,8 @@ # Block -A Block instance represents the information on a block in the bitcoin network. -Note that creating it takes some computing power, as the tree of transactions -is created or verified. +A Block instance represents the information on a block in the bitcoin network. Instantiating it is not a cheap operation, as the tree of transactions needs to be created or verified. There's a (BlockHeader)[https://github.com/bitpay/bitcore/tree/master/lib/blockheader.js] interface that is easier on the javascript VM. -Given a hexa or base64 string representation of the serialization of a block -with its transactions, you can instantiate a Block instance. It will calculate -and check the merkle root hash (if enough data is provided), but transactions -won't neccesarily be valid spends, and this class won't validate them. A binary -representation as a `Buffer` instance is also valid input for a Block's -constructor. +Given a hexa or base64 string representation of the serialization of a block with its transactions, you can instantiate a Block instance. It will calculate and check the merkle root hash (if enough data is provided), but transactions won't necessarily be valid spends, and this class won't validate them. A binary representation as a `Buffer` instance is also valid input for a Block's constructor. ```javascript assert(Block.isValidHeader(data); @@ -35,17 +28,3 @@ for (var transaction in block.transactions) { // ... } ``` - -It is also possible to explore a block's Merkle tree of transaction hashes. -Head to the [Merkle tree](./DataStructures.html#MerkleTree) documentation for -more information: - -```javascript -var root = block.tree.root; -assert(root instanceof bitcore.DataStructures.MerkleTree.Node); -assert(root.hash === block.id); -assert(root.isLeaf === false); -assert(root.left instanceof bitcore.DataStructures.MerkleTree.Node); -assert(root.right instanceof bitcore.DataStructures.MerkleTree.Node); -assert(root.left.left.left.left.content === block.transactions[0]); -``` diff --git a/docs/Crypto.md b/docs/Crypto.md index 86d5b63..f1566f3 100644 --- a/docs/Crypto.md +++ b/docs/Crypto.md @@ -1,36 +1,23 @@ # Crypto -The cryptographic primitives (ECDSA and HMAC) implementations in this package -have been audited by: - -* The BitPay engineering team +The cryptographic primitives (ECDSA and HMAC) implementations in this package have been audited bythe BitPay engineering team. More review and certifications are always welcomed. ## random -The `bitcore.Crypto.Random` namespace contains a single function, named -`getRandomBuffer(size)` that returns a `Buffer` instance with random bytes. It -may not work depending on the engine that bitcore is running on (doesn't work -with IE versions lesser than 11). +The `bitcore.Crypto.Random` namespace contains a single function, named `getRandomBuffer(size)` that returns a `Buffer` instance with random bytes. It may not work depending on the engine that bitcore is running on (doesn't work with IE versions lesser than 11). ## bn -The `bitcore.Crypto.BN` class contains a wrapper around -[bn.js](https://github.com/indutny/bn.js), the bignum library used internally -in bitcore. +The `bitcore.Crypto.BN` class contains a wrapper around [bn.js](https://github.com/indutny/bn.js), the bignum library used internally in bitcore. ## point -The `bitcore.Crypto.Point` class contains a wrapper around the class Point of -[elliptic.js](https://github.com/indutny/elliptic.js), the elliptic curve -library used internally in bitcore. +The `bitcore.Crypto.Point` class contains a wrapper around the class Point of [elliptic.js](https://github.com/indutny/elliptic.js), the elliptic curve library used internally in bitcore. ## hash -The `bitcore.Crypto.Hash` namespace contains a set of hashes and utilities. -These are either the native `crypto` hash functions from `node.js` or their -respective browser shims as provided by the `browserify` library. +The `bitcore.Crypto.Hash` namespace contains a set of hashes and utilities. These are either the native `crypto` hash functions from `node.js` or their respective browser shims as provided by the `browserify` library. ## ecdsa -`bitcore.Crypto.ECDSA` contains a pure javascript implementation of the -elliptic curve DSA signature scheme. +`bitcore.Crypto.ECDSA` contains a pure javascript implementation of the elliptic curve DSA signature scheme. diff --git a/docs/Encoding.md b/docs/Encoding.md index 565c7a7..932369b 100644 --- a/docs/Encoding.md +++ b/docs/Encoding.md @@ -1,20 +1,11 @@ # Encoding -The `bitcore.Encoding` namespace contains utilities for encoding information in -common formats in the bitcoin ecosystem. +The `bitcore.Encoding` namespace contains utilities for encoding information in common formats in the bitcoin ecosystem. ## Base58 -Two classes are provided: `Base58` and `Base58Check`. The first one merely -encodes/decodes a set of bytes in base58 format. The second one will also take -the double `sha256` hash of the information and append the last 4 bytes of the -hash as a checksum when encoding, and checking this checksum when decoding. +Two classes are provided: `Base58` and `Base58Check`. The first one merely encodes/decodes a set of bytes in base58 format. The second one will also take the double `sha256` hash of the information and append the last 4 bytes of the hash as a checksum when encoding, and check this checksum when decoding. ## BufferReader & BufferWriter These classes are used internally to write information in buffers. - -## Varint - -The bitcore implementation uses a quite complex way of compressing integers -representing the size of fields. diff --git a/docs/Hierarchical.md b/docs/Hierarchical.md index 44c0f6e..583aad8 100644 --- a/docs/Hierarchical.md +++ b/docs/Hierarchical.md @@ -1,12 +1,38 @@ # Hierarichically Derived Keys -Bitcore provides full support for -[BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki), -allowing for many key management schemas that benefit from this property. -Please be sure to read and understand the basic concepts and the warnings on -that BIP before using these classes. +Bitcore provides full support for [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki), allowing for many key management schemas that benefit from this property. Please be sure to read and understand the basic concepts and the warnings on that BIP before using these classes. ## HDPrivateKey -This class initially meant to share the interface of -[PrivateKey](http://missing-link) but add the ability to derive new keys. +An instance of a [PrivateKey](#PrivateKey.md) that also contains information required to derive child keys. + +Sample usage: + +```javascript +var hdPrivateKey = new HDPrivateKey(); +var retrieved = new HDPrivateKey('xpriv...'); +var derived = privateKey.derive("m/0'"); +var derivedByNumber = privateKey.derive(1).derive(2, true); +var derivedByArgument = privateKey.derive("m/1/2'"); +assert(derivedByNumber.xprivkey === derivedByArgument.xprivkey); + +var address = new Address(privateKey.publicKey, Networks.livenet); +var redeem = new Transaction().from(output).to(target, 10000).sign(derived.privateKey); +``` + +## HDPublicKey + +An instance of a PublicKey that can be derived to build extended public keys. Note that hardened paths are not available when deriving an HDPublicKey. + +```javascript +var hdPrivateKey = new HDPrivateKey(); +var hdPublicKey = privateKey.hdPublicKey; +try { + new HDPublicKey(); +} catch(e) { + console.log("Can't generate a public key without a private key"); +} + +var address = new Address(hdPublicKey.publicKey, Networks.livenet); +var derivedAddress = new Address(hdPublicKey.derive(100).publicKey, Networks.testnet); +``` diff --git a/docs/Input.md b/docs/Input.md deleted file mode 100644 index 135b6af..0000000 --- a/docs/Input.md +++ /dev/null @@ -1 +0,0 @@ -# Input diff --git a/docs/Output.md b/docs/Output.md deleted file mode 100644 index 22e0f66..0000000 --- a/docs/Output.md +++ /dev/null @@ -1 +0,0 @@ -# Output diff --git a/docs/Transaction.md b/docs/Transaction.md index e036ae6..5eb93bc 100644 --- a/docs/Transaction.md +++ b/docs/Transaction.md @@ -1,25 +1,12 @@ # Transaction -Bitcore provides a very simple API for creating transactions. We expect this -API to be accessible for developers without knowing the working internals of -bitcoin in deep. What follows is a small introduction to transactions with some -basic knowledge required to use this API. +Bitcore provides a very simple API for creating transactions. We expect this API to be accessible for developers without knowing the working internals of bitcoin in deep. What follows is a small introduction to transactions with some basic knowledge required to use this API. -A Transaction contains a set of inputs and a set of outputs. Each input -contains a reference to another transaction's output, and a signature -that allows the value referenced in that ouput to be used in this transaction. +A Transaction contains a set of inputs and a set of outputs. Each input contains a reference to another transaction's output, and a signature that allows the value referenced in that ouput to be used in this transaction. -Note also that an output can be used only once. That's why there's a concept of -"change address" in the bitcoin ecosystem: if an output of 10 BTC is available -for me to spend, but I only need to transmit 1 BTC, I'll create a transaction -with two outputs, one with 1 BTC that I want to spend, and the other with 9 BTC -to a change address, so I can spend this 9 BTC with another private key that I -own. +Note also that an output can be used only once. That's why there's a concept of "change address" in the bitcoin ecosystem: if an output of 10 BTC is available for me to spend, but I only need to transmit 1 BTC, I'll create a transaction with two outputs, one with 1 BTC that I want to spend, and the other with 9 BTC to a change address, so I can spend this 9 BTC with another private key that I own. -So, in order to transmit a valid transaction, you must know what other transactions -on the network store outputs that have not been spent and that are available -for you to spend (meaning that you have the set of keys that can validate you -own those funds). The unspent outputs are usually referred to as "utxo"s. +So, in order to transmit a valid transaction, you must know what other transactions on the network store outputs that have not been spent and that are available for you to spend (meaning that you have the set of keys that can validate you own those funds). The unspent outputs are usually referred to as "utxo"s. Let's take a look at some very simple transactions: @@ -29,15 +16,9 @@ var transaction = new Transaction() .to(address, amount) // Add an output with the given amount of satoshis .change(address) // Sets up a change address where the rest of the funds will go .sign(privkeySet) // Signs all the inputs it can - -var transaction2 = new Transaction() - .from(utxos) // Feed information about what unspend outputs one can use - .spendAllTo(address) // Spends all outputs into one address - .sign(privkeySet) // Signs all the inputs it can ``` -Now, one could just serialize this transaction in hexadecimal ASCII values -(`transaction.serialize()`) and send it over to the bitcoind reference client. +Now, this could just be serialized to hexadecimal ASCII values (`transaction.serialize()`) and sent over to the bitcoind reference client. ```bash bitcoin-cli sendrawtransaction @@ -45,19 +26,23 @@ bitcoin-cli sendrawtransaction ## Transaction API -You can take a look at the javadocs for the [Transaction class here](link -missing). +You can take a look at the javadocs for the [Transaction class here](link missing). + +## Input + +Transaction inputs are instances of either [Input](https://github.com/bitpay/bitcore/tree/master/lib/transaction/input) or its subclasses. The internal workings of it can be understood from the [API reference](link missing). + +## Output + +Transaction outputs are a very thin wrap around the information provided by a transaction output: its script and its output amount. ## Multisig Transactions -To send a transaction to a multisig address, the API is the same as in the -above example. To spend outputs that require multiple signatures, the process -needs extra information: the public keys of the signers that can unlock that -output. +To send a transaction to a multisig address, the API is the same as in the above example. To spend outputs that require multiple signatures, the process needs extra information: the public keys of the signers that can unlock that output. ```javascript var multiSigTx = new Transaction() - .fromMultisig(utxo, publicKeys, threshold) + .from(utxo, publicKeys, threshold) .change(address) .sign(myKeys); @@ -69,6 +54,8 @@ signatures: ```javascript var multiSigTx = new Transaction(serialized) + .from(utxo, publicKeys, threshold) // provide info about the multisig output + // (lost on serialization) .sign(anotherSetOfKeys); assert(multiSigTx.isFullySigned()); @@ -78,60 +65,23 @@ signatures: ### Internal Workings -There are a number of data structures being stored internally in a -`Transaction` instance. These are kept up to date and change through successive -calls to its methods. +There are a number of data structures being stored internally in a `Transaction` instance. These are kept up to date and change through successive calls to its methods. * `inputs`: The ordered set of inputs for this transaction * `outputs`: This is the ordered set of output scripts -* `_outpoints`: The ordered set of outpoints (a string that combines a - transaction hash and output index), UTXOs that will be inputs to this - transaction. This gets populated on calls to `from` and also when - deserializing from a serialized transaction. -* `_utxos`: Maps an outpoint to information regarding the output on that - transaction. The values of an output are: - - script: the associated script for this output. Will be an instance of - `Script` - - satoshis: amount of satoshis associated with this output - - txId: the transaction id from the outpoint - - outputIndex: the index of this output in the previous transaction -* `_inputAmount`: sum the amount for all the inputs -* `_signatures`: This is the ordered set of `scriptSig`s that are going to be - included in the serialized transaction. These are objects with the following - values: - - publicKey: the public key that generated the signature - - prevTxId: the previous transaction hash - - outputIndex: the index for the output that this input is signing - - signature: the `Signature` for that public key - - sigtype: the type of the signature (`Signature.SIGHASH_ALL` is the only one implemented) -* `_change`: stores the value provided by calling the `change` method. +* `_inputAmount`: sum of the amount for all the inputs +* `_outputAmount`: sum of the amount for all the outputs TO BE IMPLEMENTED YET: -* `_fee`: if user specified a non-standard fee, the amount (in satoshis) will - be stored in this variable so the change amount can be calculated. -* `_p2shMap`: For the case of P2SH spending, the user needs to supply - information about the script that hashes to the hash of an UTXO. This map - goes from the hash of the spend script to that script. When using the - `from(utxo, publicKeys, threshold)` function, this map gets populated with a - standard multisig spend script with public keys in the order provided. +* `_fee`: if user specified a non-standard fee, the amount (in satoshis) will be stored in this variable so the change amount can be calculated. +* `_change`: stores the value provided by calling the `change` method. ### Unspent Output Selection -If you have a larger set of unspent outputs, only some of them will be selected -to fulfill the amount. This is done by storing a cache of unspent outputs in a -protected member called `_utxos`. When the `to()` method is called, some of -these outputs will be selected to pay the requested amount to the appropriate -address. +If you have a larger set of unspent outputs, only some of them will be selected to fulfill the amount. This is done by storing a cache of unspent outputs in a protected member called `_utxos`. When the `to()` method is called, some of these outputs will be selected to pay the requested amount to the appropriate address. -A nit that you should have in mind is that when the transaction is serialized, -this cache can't be included in the serialized form. +A nit that you should have in mind is that when the transaction is serialized, this cache can't be included in the serialized form. ## Upcoming changes -We're debating an API for Merge Avoidance, CoinJoin, Smart contracts, CoinSwap, -and Stealth Addresses. We're expecting to have all of them by some time in -early 2015. - -A first draft of a Payment Channel smart contract modular extension to this -library is being implemented independently -(https://github.com/eordano/bitcore-channel). +We're debating an API for Merge Avoidance, CoinJoin, Smart contracts, CoinSwap, and Stealth Addresses. We're expecting to have all of them by some time in early 2015. First draft implementations of Payment Channel smart contracts extensions to this library are already being implemented independently. diff --git a/lib/block.js b/lib/block.js index 6ffa2c1..0140f29 100644 --- a/lib/block.js +++ b/lib/block.js @@ -24,6 +24,7 @@ var Block = function Block(arg) { return new Block(arg); } _.extend(this, Block._from(arg)); + this._setupProperties(); return this; }; @@ -53,6 +54,29 @@ Block._from = function _from(arg) { return info; }; +/** + * Internal function that sets up a some properties from blockheader for + * easier access + */ +Block.prototype._setupProperties = function() { + Object.defineProperty(this, 'version', { + configurable: false, + value: this.blockheader.version + }); + Object.defineProperty(this, 'timestamp', { + configurable: false, + value: this.blockheader.timestamp + }); + Object.defineProperty(this, 'nonce', { + configurable: false, + value: this.blockheader.nonce + }); + Object.defineProperty(this, 'size', { + configurable: false, + value: this.blockheader.size + }); +}; + /** * @param {String|Object} - A JSON string or object * @returns {Object} - An object representing block data @@ -236,7 +260,6 @@ Block.prototype.getMerkleTree = function getMerkleTree() { } return tree; - }; /** diff --git a/lib/blockheader.js b/lib/blockheader.js index 2fdf9b4..290ac58 100644 --- a/lib/blockheader.js +++ b/lib/blockheader.js @@ -40,8 +40,10 @@ BlockHeader._from = function _from(arg) { info = { version: arg.version, prevblockidbuf: arg.prevblockidbuf, + prevHash: arg.prevblockidbuf, merklerootbuf: arg.merklerootbuf, time: arg.time, + timestamp: arg.time, bits: arg.bits, nonce: arg.nonce }; @@ -63,8 +65,10 @@ BlockHeader._fromJSON = function _fromJSON(data) { var info = { version: data.version, prevblockidbuf: new Buffer(data.prevblockidbuf, 'hex'), + prevHash: new Buffer(data.prevblockidbuf, 'hex'), merklerootbuf: new Buffer(data.merklerootbuf, 'hex'), time: data.time, + timestamp: data.time, bits: data.bits, nonce: data.nonce };