├── .gitignore
├── .groc.json
├── .karma.conf.js
├── .npmignore
├── .nvmrc
├── .travis.yml
├── LICENSE
├── README.md
├── bin
├── test-parallel
├── testapp.js
└── yours-bitcoin.js
├── build
└── index.html
├── config.js
├── gulpfile.js
├── index.js
├── lib
├── ach.js
├── addr.js
├── address.js
├── aes.js
├── aescbc.js
├── base-58-check.js
├── base-58.js
├── bip-32.js
├── bip-39-en.js
├── bip-39-jp.js
├── bip-39.js
├── bip-68.js
├── block-header.js
├── block.js
├── bn.js
├── br.js
├── bsm.js
├── bw.js
├── cbc.js
├── cmp.js
├── constants.js
├── ecdsa.js
├── ecies.js
├── get-blocks.js
├── hash.js
├── interp.js
├── inv.js
├── kdf.js
├── key-pair.js
├── merkle.js
├── msg-addr.js
├── msg-alert.js
├── msg-block.js
├── msg-get-addr.js
├── msg-get-blocks.js
├── msg-get-data.js
├── msg-get-headers.js
├── msg-headers.js
├── msg-inv.js
├── msg-mem-pool.js
├── msg-not-found.js
├── msg-ping.js
├── msg-pong.js
├── msg-reject.js
├── msg-send-headers.js
├── msg-tx.js
├── msg-ver-ack.js
├── msg-version.js
├── msg.js
├── op-code.js
├── point.js
├── priv-key.js
├── pub-key.js
├── random.js
├── reject.js
├── script.js
├── sig.js
├── struct.js
├── tx-builder.js
├── tx-in.js
├── tx-out-map.js
├── tx-out.js
├── tx-verifier.js
├── tx.js
├── var-int.js
├── version.js
├── worker-browser.js
├── worker-node.js
├── workers-cmd.js
├── workers-result.js
└── workers.js
├── npm-shrinkwrap.json
├── package.json
└── test
├── ach.js
├── addr.js
├── address.js
├── aes.js
├── aescbc.js
├── base-58-check.js
├── base-58.js
├── bip-32.js
├── bip-39.js
├── bip-68.js
├── block-header.js
├── block.js
├── bn.js
├── br.js
├── bsm.js
├── bw.js
├── cbc.js
├── cmp.js
├── ecdsa.js
├── ecies.js
├── get-blocks.js
├── global.js
├── hash.js
├── helpers
├── interp.js
└── tx-verifier.js
├── index.js
├── interp-vectors-1.js
├── interp-vectors-2.js
├── interp-vectors-3.js
├── interp-vectors-4.js
├── interp.js
├── inv.js
├── kdf.js
├── key-pair.js
├── merkle.js
├── msg-addr.js
├── msg-alert.js
├── msg-block.js
├── msg-get-addr.js
├── msg-get-blocks.js
├── msg-get-data.js
├── msg-get-headers.js
├── msg-headers.js
├── msg-inv.js
├── msg-mem-pool.js
├── msg-not-found.js
├── msg-ping.js
├── msg-pong.js
├── msg-reject.js
├── msg-send-header.js
├── msg-tx.js
├── msg-ver-ack.js
├── msg-version.js
├── msg.js
├── op-code.js
├── point.js
├── priv-key.js
├── pub-key.js
├── random.js
├── reject.js
├── script.js
├── sig.js
├── struct.js
├── tx-builder.js
├── tx-in.js
├── tx-out-map.js
├── tx-out.js
├── tx-verifier-vectors-1.js
├── tx-verifier-vectors-2.js
├── tx-verifier-vectors-3.js
├── tx-verifier-vectors-4.js
├── tx-verifier.js
├── tx.js
├── var-int.js
├── vectors
├── aes.json
├── aescbc.json
├── bip39.json
├── bitcoind
│ ├── script_invalid.json
│ ├── script_valid.json
│ ├── sighash.json
│ ├── tx_invalid.json
│ └── tx_valid.json
├── coolest-tx-ever-sent.json
├── ecdsa.json
├── hash.json
├── kdf.json
├── largesttx.json
├── largesttxblock.json
├── sig.json
└── sighash-single-bug.json
├── version.js
├── workers-cmd.js
├── workers-result.js
└── workers.js
/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | coverage
3 | node_modules
4 | build/yours-bitcoin.js
5 | build/yours-bitcoin-worker.js
6 | build/yours-bitcoin-min.js
7 | build/yours-bitcoin-worker-min.js
8 | build/tests.js
9 | npm-debug.log
10 | doc
11 |
--------------------------------------------------------------------------------
/.groc.json:
--------------------------------------------------------------------------------
1 | {
2 | "glob": ["README.md", "lib/*.js", "lib/**/*.js", "lib/**/**/*.js", "examples/*.js"]
3 | }
4 |
--------------------------------------------------------------------------------
/.karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration
2 | // Generated on Tue Jan 06 2015 16:30:03 GMT-0800 (PST)
3 |
4 | module.exports = function(config) {
5 | config.set({
6 |
7 | // base path that will be used to resolve all patterns (eg. files, exclude)
8 | basePath: 'build',
9 |
10 |
11 | // frameworks to use
12 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
13 | frameworks: ['mocha'],
14 |
15 |
16 | // list of files / patterns to load in the browser
17 | files: [
18 | {pattern: 'yours-bitcoin.js', watched: true, included: true, served: true},
19 | {pattern: 'yours-bitcoin-worker.js', watched: true, included: false, served: true},
20 | 'tests.js'
21 | ],
22 |
23 |
24 | // list of files to exclude
25 | exclude: [
26 | ],
27 |
28 |
29 | // preprocess matching files before serving them to the browser
30 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
31 | preprocessors: {
32 | },
33 |
34 |
35 | // test results reporter to use
36 | // possible values: 'dots', 'progress'
37 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter
38 | reporters: ['progress'],
39 |
40 |
41 | // web server port
42 | port: 9876,
43 |
44 |
45 | // enable / disable colors in the output (reporters and logs)
46 | colors: true,
47 |
48 |
49 | // level of logging
50 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
51 | logLevel: config.LOG_DEBUG,
52 |
53 |
54 | // enable / disable watching file and executing tests whenever any file changes
55 | autoWatch: false,
56 |
57 |
58 | // start these browsers
59 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
60 | browsers: ['Firefox'],
61 |
62 |
63 | // Continuous Integration mode
64 | // if true, Karma captures browsers, runs the tests and exits
65 | singleRun: true
66 | });
67 | };
68 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | build
3 | coverage
4 | test
5 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 6.1
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - '4.3'
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016 Yours Inc.
2 |
3 | Copyright (c) 2014-2016 Ryan X. Charles
4 |
5 | Parts of this software are based on Bitcoin Core
6 | Copyright (c) 2009-2016 The Bitcoin Core developers
7 |
8 | Parts of this software were developed by reddit
9 | Copyright (c) 2014 reddit, Inc.
10 |
11 | Parts of this software are based on bitcore
12 | Copyright (c) 2014 BitPay Inc.
13 |
14 | Parts of this software are based on BitcoinJS
15 | Copyright (c) 2011-2014 Bitcoinjs-lib contributors
16 |
17 | Parts of this software are based on BitcoinJ
18 | Copyright (c) 2011 Google Inc.
19 |
20 | Permission is hereby granted, free of charge, to any person obtaining a copy
21 | of this software and associated documentation files (the "Software"), to deal
22 | in the Software without restriction, including without limitation the rights
23 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24 | copies of the Software, and to permit persons to whom the Software is
25 | furnished to do so, subject to the following conditions:
26 |
27 | The above copyright notice and this permission notice shall be included in
28 | all copies or substantial portions of the Software.
29 |
30 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
36 | THE SOFTWARE.
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Yours Bitcoin
2 | =============
3 |
4 | Yours Bitcoin is a javascript implementation of bitcoin intended to satisfy
5 | certain goals:
6 |
7 | 1. Bring the blockchain to web browsers and node.js in a decentralized,
8 | trust-minimized manner, without the required use of a third-party API.
9 |
10 | 2. Support ease-of-use by being internally consistent. It should not be
11 | necessary to read the source code of a class or function to know how to use it.
12 | Once you know how to use part of the library, the other parts should feel
13 | natural.
14 |
15 | 3. Have 100% test coverage, or nearly so, so that the library is known to be
16 | reliable. This should include running standard test vectors from the reference
17 | implementation.
18 |
19 | 4. Library objects have an interface suitable for use with a command-line
20 | interface or other libraries and tools, in particular having toString,
21 | fromString, toJSON, fromJSON, toBuffer, fromBuffer, toHex, fromHex methods.
22 |
23 | 5. All standard features of the blockchain are implemented (or will be) and
24 | saved in lib/. All BIPs are correctly implemented and, where appropriate, saved
25 | as bip-xx.js in lib/ (since that is their standard name). In order to allow
26 | rapid development, Yours Bitcoin includes non-standard and experimental
27 | features. Any non-standard features (such as colored coins or stealth
28 | addresses) are labeled as such in index.js as well as in comments.
29 |
30 | 6. Expose everything, including dependencies. This makes it possible to develop
31 | apps that require fine-grained control over the basics, such as big numbers and
32 | points. However, it also means that you can hurt yourself if you misuse these
33 | primitives.
34 |
35 | 7. Use standard javascript conventions wherever possible so that other
36 | developers find the code easy to understand.
37 |
38 | 8. Minimize the use of dependencies so that all code can be easily audited.
39 |
40 | 9. All instance methods modify the state of the object and return the object,
41 | unless there is a good reason to do something different. To access the result
42 | of an instance method, you must access the object property(s) that it modifies.
43 |
44 | Yours Bitcoin is still being developed and does not yet support downloading the
45 | blockchain.
46 |
47 | Environment Variables
48 | ---------------------
49 | - `YOURS_BITCOIN_JS_BASE_URL` - Default "/".
50 | - `YOURS_BITCOIN_JS_BUNDLE_FILE` - Default "yours-bitcoin.js"
51 | - `YOURS_BITCOIN_JS_WORKER_FILE` - Default "yours-bitcoin-worker.js"
52 | - `YOURS_BITCOIN_JS_BUNDLE_MIN_FILE` - Default "yours-bitcoin-min.js"
53 | - `YOURS_BITCOIN_JS_WORKER_MIN_FILE` - Default "yours-bitcoin-worker-min.js"
54 | - `YOURS_BITCOIN_NETWORK` - Default "mainnet"
55 |
56 | You can change the network to run the CLI in testnet mode:
57 | ```
58 | YOURS_BITCOIN_NETWORK=testnet ./bin/yours-bitcoin.js
59 | ```
60 |
61 | Documentation
62 | -------------
63 |
64 | While Yours Bitcoin is under heavy development, the API changes frequently, and
65 | the documentation is not kept up-to-date. However there is some documentation,
66 | and it can be built with groc:
67 |
68 | ```
69 | npm install -g groc
70 | groc
71 | ```
72 |
73 | Database Proposal
74 | -----------------
75 | ```
76 | block-[blockHashBuf]:[height][blockBuf]
77 | height-[height][blockHashBuf]:[workSum]
78 | work-[workSum][blockHashBuf]:
79 | tx-[txHashBuf]:[txBuf]
80 | address-[addressBuf]:[satoshiDiffBn, height, blockHashBuf, txHashBuf] (removed on reorg)
81 | chain-[height]:[blockHashBuf] (removed on reorg)
82 | ```
83 |
--------------------------------------------------------------------------------
/bin/test-parallel:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # This test runner passes a list of every 4th test file into 4 simultaneous
4 | # mocha processes so it can use 4 cores efficiently. This should run no faster
5 | # than 4 times faster than series. In practice, it runs about twice as fast on
6 | # a 4 core machine. You must execute this from the project root directory. You
7 | # must have "parallel" installed for this to work. On Ubuntu: "apt-get install
8 | # parallel".
9 |
10 | echo "Executing mocha tests in 6 processes."
11 |
12 | ls test/*.js \
13 | | tee \
14 | >(sed -n "p;n;n;n;n;n;" | xargs echo mocha -R progress) \
15 | >(sed -n "n;p;n;n;n;n;" | xargs echo mocha -R progress) \
16 | >(sed -n "n;n;p;n;n;n;" | xargs echo mocha -R progress) \
17 | >(sed -n "n;n;n;p;n;n;" | xargs echo mocha -R progress) \
18 | >(sed -n "n;n;n;n;p;n;" | xargs echo mocha -R progress) \
19 | >(sed -n "n;n;n;n;n;p;" | xargs echo mocha -R progress) \
20 | > /dev/null \
21 | | parallel
22 |
--------------------------------------------------------------------------------
/bin/testapp.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | /**
3 | * Basic web app to facilitate running the mocha browser tests without karma.
4 | */
5 | 'use strict'
6 | let express = require('express')
7 | let path = require('path')
8 | let app = express()
9 |
10 | app.use(express.static(path.join(__dirname, '../build')))
11 | app.use(express.static(path.join(__dirname, '../node_modules')))
12 |
13 | let server = app.listen(3000, function () {
14 | let host = server.address().address
15 | let port = server.address().port
16 | console.log('Run the mocha tests at http://%s:%s/', host, port)
17 | })
18 |
19 | module.exports.app = app
20 | module.exports.server = server
21 |
--------------------------------------------------------------------------------
/bin/yours-bitcoin.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | 'use strict'
3 | let repl = require('repl')
4 | let YoursBitcoin = require('../')
5 | // Make all Fullnode classes globally available.
6 | Object.assign(global, YoursBitcoin, {YoursBitcoin: YoursBitcoin})
7 | repl.start({
8 | prompt: 'yours-bitcoin> ',
9 | useGlobal: true,
10 | ignoreUndefined: true
11 | })
12 |
--------------------------------------------------------------------------------
/build/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Mocha
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/config.js:
--------------------------------------------------------------------------------
1 | // By default, we assume browser-loaded javascript is served from the root
2 | // directory, "/", of the http server. karma, however, assumes files are in the
3 | // "/base/" directory, thus we invented this variable to allow overriding the
4 | // directory. If you wish to put your javascript somewhere other than root,
5 | // specify it by setting this environment variable before building. You can
6 | // also override the name of the bundle and worker files or the minified
7 | // versions by setting the respective environment variables below.
8 | if (!process.env.YOURS_BITCOIN_JS_BASE_URL) {
9 | process.env.YOURS_BITCOIN_JS_BASE_URL = '/'
10 | }
11 |
12 | if (!process.env.YOURS_BITCOIN_JS_BUNDLE_FILE) {
13 | process.env.YOURS_BITCOIN_JS_BUNDLE_FILE = 'yours-bitcoin.js'
14 | }
15 |
16 | if (!process.env.YOURS_BITCOIN_JS_WORKER_FILE) {
17 | process.env.YOURS_BITCOIN_JS_WORKER_FILE = 'yours-bitcoin-worker.js'
18 | }
19 |
20 | if (!process.env.YOURS_BITCOIN_JS_BUNDLE_MIN_FILE) {
21 | process.env.YOURS_BITCOIN_JS_BUNDLE_MIN_FILE = 'yours-bitcoin-min.js'
22 | }
23 |
24 | if (!process.env.YOURS_BITCOIN_JS_WORKER_MIN_FILE) {
25 | process.env.YOURS_BITCOIN_JS_WORKER_MIN_FILE = 'yours-bitcoin-worker-min.js'
26 | }
27 |
28 | if (!process.env.YOURS_BITCOIN_NETWORK) {
29 | process.env.YOURS_BITCOIN_NETWORK = 'mainnet'
30 | }
31 |
--------------------------------------------------------------------------------
/lib/ach.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Ach (Aes+Cbc+Hmac) (experimental)
3 | * =================================
4 | *
5 | * An "encrypt-then-MAC" that uses Aes, Cbc and SHA256 Hmac. This is suitable
6 | * for general encryption of data.
7 | *
8 | * The encrypted data takes the form:
9 | * (256 bit hmac)(128 bit iv)(128+ bits Aes+Cbc encrypted message)
10 | */
11 | 'use strict'
12 | let dependencies = {
13 | Aescbc: require('./aescbc'),
14 | Hash: require('./hash'),
15 | Random: require('./random'),
16 | Workers: require('./workers'),
17 | asink: require('asink'),
18 | cmp: require('./cmp')
19 | }
20 |
21 | let inject = function (deps) {
22 | let Aescbc = deps.Aescbc
23 | let Hash = deps.Hash
24 | let Random = deps.Random
25 | let Workers = deps.Workers
26 | let asink = deps.asink
27 | let cmp = deps.cmp
28 |
29 | let Ach = {}
30 |
31 | Ach.encrypt = function (messageBuf, cipherKeyBuf, ivBuf) {
32 | let encBuf = Aescbc.encrypt(messageBuf, cipherKeyBuf, ivBuf)
33 | let hmacbuf = Hash.sha256Hmac(encBuf, cipherKeyBuf)
34 | return Buffer.concat([hmacbuf, encBuf])
35 | }
36 |
37 | Ach.asyncEncrypt = function (messageBuf, cipherKeyBuf, ivBuf) {
38 | return asink(function * () {
39 | if (!ivBuf) {
40 | ivBuf = Random.getRandomBuffer(128 / 8)
41 | }
42 | let args = [messageBuf, cipherKeyBuf, ivBuf]
43 | let workersResult = yield Workers.asyncClassMethod('Ach', 'encrypt', args)
44 | return workersResult.resbuf
45 | }, this)
46 | }
47 |
48 | Ach.decrypt = function (encBuf, cipherKeyBuf) {
49 | if (encBuf.length < (256 + 128 + 128) / 8) {
50 | throw new Error('The encrypted data must be at least 256+128+128 bits, which is the length of the Hmac plus the iv plus the smallest encrypted data size')
51 | }
52 | let hmacbuf = encBuf.slice(0, 256 / 8)
53 | encBuf = encBuf.slice(256 / 8, encBuf.length)
54 | let hmacbuf2 = Hash.sha256Hmac(encBuf, cipherKeyBuf)
55 | if (!cmp(hmacbuf, hmacbuf2)) {
56 | throw new Error('Message authentication failed - Hmacs are not equivalent')
57 | }
58 | return Aescbc.decrypt(encBuf, cipherKeyBuf)
59 | }
60 |
61 | Ach.asyncDecrypt = function (encBuf, cipherKeyBuf) {
62 | return asink(function * () {
63 | let args = [encBuf, cipherKeyBuf]
64 | let workersResult = yield Workers.asyncClassMethod('Ach', 'decrypt', args)
65 | return workersResult.resbuf
66 | }, this)
67 | }
68 |
69 | return Ach
70 | }
71 |
72 | inject = require('injecter')(inject, dependencies)
73 | let Ach = inject()
74 | module.exports = Ach
75 |
--------------------------------------------------------------------------------
/lib/addr.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Addr
3 | * ====
4 | *
5 | * An IP address and port. Note that "Addr" is completely different from
6 | * "Address". Addr is an IP address and port of a bitcoin node on the network
7 | * for connecting to using the bitcoin p2p protocol. Address is a bitcoin
8 | * address for sending a payment to.
9 | */
10 | 'use strict'
11 | let dependencies = {
12 | Bw: require('./bw'),
13 | Struct: require('./struct')
14 | }
15 |
16 | let inject = function (deps) {
17 | let Bw = deps.Bw
18 | let Struct = deps.Struct
19 |
20 | class Addr extends Struct {
21 | constructor (time, servicesBuf, ipAddrBuf, port) {
22 | super({time, servicesBuf, ipAddrBuf, port})
23 | }
24 |
25 | toBw (bw) {
26 | if (!bw) {
27 | bw = new Bw()
28 | }
29 | bw.writeUInt32LE(this.time) // note LE
30 | bw.write(this.servicesBuf)
31 | bw.write(this.ipAddrBuf)
32 | bw.writeUInt16BE(this.port) // note BE
33 | return bw
34 | }
35 |
36 | fromBr (br) {
37 | this.time = br.readUInt32LE() // note LE
38 | this.servicesBuf = br.read(8)
39 | this.ipAddrBuf = br.read(16)
40 | this.port = br.readUInt16BE() // note BE
41 | return this
42 | }
43 | }
44 |
45 | return Addr
46 | }
47 |
48 | inject = require('injecter')(inject, dependencies)
49 | let Addr = inject()
50 | module.exports = Addr
51 |
--------------------------------------------------------------------------------
/lib/aes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Aes (experimental)
3 | * ==================
4 | *
5 | * Advanced Encryption Standard (Aes). This is a low-level tool for encrypting
6 | * or decrypting blocks of data. There is almost never a reason to use this -
7 | * don't use it unless you need to encrypt or decrypt individual blocks.
8 | */
9 | 'use strict'
10 | let dependencies = {
11 | _Aes: require('aes')
12 | }
13 |
14 | let inject = function (deps) {
15 | let _Aes = deps._Aes
16 | let Aes = {}
17 |
18 | Aes.encrypt = function (messageBuf, keyBuf) {
19 | let key = Aes.buf2Words(keyBuf)
20 | let message = Aes.buf2Words(messageBuf)
21 | let a = new _Aes(key)
22 | let enc = a.encrypt(message)
23 | let encBuf = Aes.words2Buf(enc)
24 | return encBuf
25 | }
26 |
27 | Aes.decrypt = function (encBuf, keyBuf) {
28 | let enc = Aes.buf2Words(encBuf)
29 | let key = Aes.buf2Words(keyBuf)
30 | let a = new _Aes(key)
31 | let message = a.decrypt(enc)
32 | let messageBuf = Aes.words2Buf(message)
33 | return messageBuf
34 | }
35 |
36 | Aes.buf2Words = function (buf) {
37 | if (buf.length % 4) {
38 | throw new Error('buf length must be a multiple of 4')
39 | }
40 |
41 | let words = []
42 |
43 | for (let i = 0; i < buf.length / 4; i++) {
44 | words.push(buf.readUInt32BE(i * 4))
45 | }
46 |
47 | return words
48 | }
49 |
50 | Aes.words2Buf = function (words) {
51 | let buf = new Buffer(words.length * 4)
52 |
53 | for (let i = 0; i < words.length; i++) {
54 | buf.writeUInt32BE(words[i], i * 4)
55 | }
56 |
57 | return buf
58 | }
59 |
60 | return Aes
61 | }
62 |
63 | inject = require('injecter')(inject, dependencies)
64 | let Aes = inject()
65 | module.exports = Aes
66 |
--------------------------------------------------------------------------------
/lib/aescbc.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Aescbc (experimental)
3 | * =====================
4 | *
5 | * This is a convenience class for using Aes with Cbc. This is a low-level tool
6 | * that does not include authentication. You should only use this if you are
7 | * authenticating your data somehow else.
8 | */
9 | 'use strict'
10 | let dependencies = {
11 | Aes: require('./aes'),
12 | Cbc: require('./cbc'),
13 | Random: require('./random')
14 | }
15 |
16 | let inject = function (deps) {
17 | let Aes = deps.Aes
18 | let Cbc = deps.Cbc
19 | let Random = deps.Random
20 | let Aescbc = {}
21 |
22 | Aescbc.encrypt = function (messageBuf, cipherKeyBuf, ivBuf) {
23 | ivBuf = ivBuf || Random.getRandomBuffer(128 / 8)
24 | let ctBuf = Cbc.encrypt(messageBuf, ivBuf, Aes, cipherKeyBuf)
25 | return Buffer.concat([ivBuf, ctBuf])
26 | }
27 |
28 | Aescbc.decrypt = function (encBuf, cipherKeyBuf) {
29 | let ivBuf = encBuf.slice(0, 128 / 8)
30 | let ctBuf = encBuf.slice(128 / 8)
31 | return Cbc.decrypt(ctBuf, ivBuf, Aes, cipherKeyBuf)
32 | }
33 |
34 | return Aescbc
35 | }
36 |
37 | inject = require('injecter')(inject, dependencies)
38 | let Aescbc = inject()
39 | module.exports = Aescbc
40 |
--------------------------------------------------------------------------------
/lib/base-58-check.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Base58 Check Encoding
3 | * =====================
4 | *
5 | * Base58 check encoding. The usual way to use it is
6 | * new Base58Check(buf).toString() or new Base58Check(str).toBuffer().
7 | */
8 | 'use strict'
9 | let dependencies = {
10 | Base58: require('./base-58'),
11 | cmp: require('./cmp'),
12 | Hash: require('./hash'),
13 | Struct: require('./struct')
14 | }
15 |
16 | let inject = function (deps) {
17 | let Base58 = deps.Base58
18 | let cmp = deps.cmp
19 | let Hash = deps.Hash
20 | let Struct = deps.Struct
21 |
22 | class Base58Check extends Struct {
23 | constructor (buf) {
24 | super({buf})
25 | }
26 |
27 | fromHex (hex) {
28 | return this.fromBuffer(new Buffer(hex, 'hex'))
29 | }
30 |
31 | toHex () {
32 | return this.toBuffer().toString('hex')
33 | }
34 |
35 | static decode (s) {
36 | if (typeof s !== 'string') {
37 | throw new Error('Input must be a string')
38 | }
39 |
40 | let buf = Base58.decode(s)
41 |
42 | if (buf.length < 4) {
43 | throw new Error('Input string too short')
44 | }
45 |
46 | let data = buf.slice(0, -4)
47 | let csum = buf.slice(-4)
48 |
49 | let hash = Hash.sha256Sha256(data)
50 | let hash4 = hash.slice(0, 4)
51 |
52 | if (!cmp(csum, hash4)) {
53 | throw new Error('Checksum mismatch')
54 | }
55 |
56 | return data
57 | }
58 |
59 | static encode (buf) {
60 | if (!Buffer.isBuffer(buf)) {
61 | throw new Error('Input must be a buffer')
62 | }
63 | let checkedBuf = new Buffer(buf.length + 4)
64 | let hash = Hash.sha256Sha256(buf)
65 | buf.copy(checkedBuf)
66 | hash.copy(checkedBuf, buf.length)
67 | return Base58.encode(checkedBuf)
68 | }
69 |
70 | fromBuffer (buf) {
71 | this.buf = buf
72 | return this
73 | }
74 |
75 | fromString (str) {
76 | let buf = Base58Check.decode(str)
77 | this.buf = buf
78 | return this
79 | }
80 |
81 | toBuffer () {
82 | return this.buf
83 | }
84 |
85 | toString () {
86 | return Base58Check.encode(this.buf)
87 | }
88 | }
89 |
90 | return Base58Check
91 | }
92 |
93 | inject = require('injecter')(inject, dependencies)
94 | let Base58Check = inject()
95 | module.exports = Base58Check
96 |
--------------------------------------------------------------------------------
/lib/base-58.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Base58 Encoding
3 | * ===============
4 | *
5 | * Base58 (no check)
6 | */
7 | 'use strict'
8 | let dependencies = {
9 | bs58: require('bs58'),
10 | Struct: require('./struct')
11 | }
12 |
13 | let inject = function (deps) {
14 | let bs58 = deps.bs58
15 | let Struct = deps.Struct
16 |
17 | class Base58 extends Struct {
18 | constructor (buf) {
19 | super({buf})
20 | }
21 |
22 | fromHex (hex) {
23 | return this.fromBuffer(new Buffer(hex, 'hex'))
24 | }
25 |
26 | toHex () {
27 | return this.toBuffer().toString('hex')
28 | }
29 |
30 | static encode (buf) {
31 | if (!Buffer.isBuffer(buf)) {
32 | throw new Error('Input should be a buffer')
33 | }
34 | return bs58.encode(buf)
35 | }
36 |
37 | static decode (str) {
38 | if (typeof str !== 'string') {
39 | throw new Error('Input should be a string')
40 | }
41 | return new Buffer(bs58.decode(str))
42 | }
43 |
44 | fromBuffer (buf) {
45 | this.buf = buf
46 | return this
47 | }
48 |
49 | fromString (str) {
50 | let buf = Base58.decode(str)
51 | this.buf = buf
52 | return this
53 | }
54 |
55 | toBuffer () {
56 | return this.buf
57 | }
58 |
59 | toString () {
60 | return Base58.encode(this.buf)
61 | }
62 | }
63 |
64 | return Base58
65 | }
66 |
67 | inject = require('injecter')(inject, dependencies)
68 | let Base58 = inject()
69 | module.exports = Base58
70 |
--------------------------------------------------------------------------------
/lib/bip-68.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Bip68: Relative Lock-Time
3 | * =========================
4 | *
5 | * Bip68 is an important change to the interpretation of sequence numbers in
6 | * transaction inputs (called nSequence in Yours Bitcoin). Originally, sequence
7 | * numbers specified which transaction was the most "up-to-date" version, but
8 | * they did so only insecurely. BEcause they were insecure, they were disabled,
9 | * and became and almost meanIngless piece of data. Opt-in RBF (Replace-By-Fee)
10 | * changed that slightly by interpreting non-maximal sequence numbers to be
11 | * replaceable with greater fees. Bip68 reinterprets sequence numbers entirely
12 | * as relative lock-time. If the sequence number, appropriately masked, is
13 | * lower than the number of blocks since the input transaction was confirmed,
14 | * then the transaction is invalid.
15 | *
16 | * This class will embody the code from the Bip68 spec. However, some of that
17 | * code requires full node support, which (ironically) Yours Bitcoin does not yet
18 | * support. So it will be finished when appropriate.
19 | *
20 | * These functions will need to be added to this class:
21 | * CalculateSequenceLocks
22 | * EvaluateSequenceLocks
23 | * SequenceLocks
24 | * CheckSequenceLocks
25 | */
26 | 'use strict'
27 |
28 | let dependencies = {
29 | Struct: require('./struct'),
30 | TxIn: require('./tx-in')
31 | }
32 |
33 | let inject = function (deps) {
34 | let Struct = deps.Struct
35 | let TxIn = deps.TxIn
36 |
37 | class Bip68 extends Struct {
38 | static nSequence2Height (nSequence) {
39 | return nSequence & TxIn.SEQUENCE_LOCKTIME_MASK
40 | }
41 |
42 | // 0 <= height < 65,535 blocks (1.25 years)
43 | static height2NSequence (height) {
44 | return height
45 | }
46 |
47 | static nSequence2Time (nSequence) {
48 | return (nSequence & TxIn.SEQUENCE_LOCKTIME_MASK) << TxIn.SEQUENCE_LOCKTIME_GRANULARITY
49 | }
50 |
51 | // 0 <= time < 33,554,431 seconds (1.06 years)
52 | static time2NSequence (time) {
53 | return TxIn.SEQUENCE_LOCKTIME_TYPE_FLAG | (time >> TxIn.SEQUENCE_LOCKTIME_GRANULARITY)
54 | }
55 |
56 | /**
57 | * Whether Bip68 is disabled for this nSequence.
58 | */
59 | static nSequenceIsDisabled (nSequence) {
60 | return (nSequence & TxIn.SEQUENCE_LOCKTIME_DISABLE_FLAG) !== 0
61 | }
62 |
63 | /**
64 | * true if time, false if height
65 | */
66 | static nSequenceIsTime (nSequence) {
67 | return (nSequence & TxIn.SEQUENCE_LOCKTIME_TYPE_FLAG) !== 0
68 | }
69 |
70 | /**
71 | * Get the "value" masked out of this nSequence - can be converted to time or
72 | * height.
73 | */
74 | static nSequenceValue (nSequence) {
75 | return nSequence & TxIn.SEQUENCE_LOCKTIME_MASK
76 | }
77 | }
78 |
79 | return Bip68
80 | }
81 |
82 | inject = require('injecter')(inject, dependencies)
83 | let Bip68 = inject()
84 | module.exports = Bip68
85 |
--------------------------------------------------------------------------------
/lib/block-header.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Block Header
3 | * ============
4 | *
5 | * Every block contains a blockHeader. This is probably not something you will
6 | * personally use, but it's here if you need it.
7 | */
8 | 'use strict'
9 | let dependencies = {
10 | Bw: require('./bw'),
11 | Struct: require('./struct')
12 | }
13 |
14 | let inject = function (deps) {
15 | let Bw = deps.Bw
16 | let Struct = deps.Struct
17 |
18 | class BlockHeader extends Struct {
19 | constructor (versionBytesNum, prevBlockHashBuf, merkleRootBuf, time, bits, nonce) {
20 | super({versionBytesNum, prevBlockHashBuf, merkleRootBuf, time, bits, nonce})
21 | }
22 |
23 | fromJSON (json) {
24 | this.fromObject({
25 | versionBytesNum: json.versionBytesNum,
26 | prevBlockHashBuf: new Buffer(json.prevBlockHashBuf, 'hex'),
27 | merkleRootBuf: new Buffer(json.merkleRootBuf, 'hex'),
28 | time: json.time,
29 | bits: json.bits,
30 | nonce: json.nonce
31 | })
32 | return this
33 | }
34 |
35 | toJSON () {
36 | return {
37 | versionBytesNum: this.versionBytesNum,
38 | prevBlockHashBuf: this.prevBlockHashBuf.toString('hex'),
39 | merkleRootBuf: this.merkleRootBuf.toString('hex'),
40 | time: this.time,
41 | bits: this.bits,
42 | nonce: this.nonce
43 | }
44 | }
45 |
46 | fromBr (br) {
47 | this.versionBytesNum = br.readUInt32LE()
48 | this.prevBlockHashBuf = br.read(32)
49 | this.merkleRootBuf = br.read(32)
50 | this.time = br.readUInt32LE()
51 | this.bits = br.readUInt32LE()
52 | this.nonce = br.readUInt32LE()
53 | return this
54 | }
55 |
56 | toBw (bw) {
57 | if (!bw) {
58 | bw = new Bw()
59 | }
60 | bw.writeUInt32LE(this.versionBytesNum)
61 | bw.write(this.prevBlockHashBuf)
62 | bw.write(this.merkleRootBuf)
63 | bw.writeUInt32LE(this.time)
64 | bw.writeUInt32LE(this.bits)
65 | bw.writeUInt32LE(this.nonce)
66 | return bw
67 | }
68 | }
69 |
70 | return BlockHeader
71 | }
72 |
73 | inject = require('injecter')(inject, dependencies)
74 | let BlockHeader = inject()
75 | module.exports = BlockHeader
76 |
--------------------------------------------------------------------------------
/lib/cmp.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Constant-Time Buffer Compare
3 | * ============================
4 | *
5 | * A constant-time comparison function. This should be used in any security
6 | * sensitive code where leaking timing information may lead to lessened
7 | * security. Note that if the buffers are not equal in length, this function
8 | * loops for the longest buffer, which may not be necessary. Usually this
9 | * function should be used for buffers that would otherwise be equal length,
10 | * such as a hash, particularly Hmacs.
11 | *
12 | * The algorithm here, which is XORs each byte (or, if undefined, 0) with the
13 | * corresponding other byte, and then ORs that with a running total (d), is
14 | * adapted from here:
15 | *
16 | * https://groups.google.com/forum/#!topic/keyczar-discuss/VXHsoJSLKhM
17 | */
18 | 'use strict'
19 | module.exports = function cmp (buf1, buf2) {
20 | if (!Buffer.isBuffer(buf1) || !Buffer.isBuffer(buf2)) {
21 | throw new Error('buf1 and buf2 must be buffers')
22 | }
23 | if (buf1.length !== buf2.length) {
24 | return false
25 | }
26 |
27 | let d = 0
28 | for (let i = 0; i < buf1.length; i++) {
29 | let x = buf1[i]
30 | let y = buf2[i]
31 | d |= (x ^ y)
32 | }
33 |
34 | return d === 0
35 | }
36 |
--------------------------------------------------------------------------------
/lib/constants.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Constants
3 | * =========
4 | *
5 | * Constants used to distinguish mainnet from testnet.
6 | */
7 | 'use strict'
8 |
9 | let Constants = module.exports
10 |
11 | Constants.Mainnet = {
12 | maxsize: 0x02000000, // MAX_SIZE
13 | Address: {
14 | pubKeyHash: 0x00,
15 | scriptHash: 0x05
16 | },
17 | Bip32: {
18 | pubKey: 0x0488b21e,
19 | privKey: 0x0488ade4
20 | },
21 | Block: {
22 | maxNBits: 0x1d00ffff,
23 | magicNum: 0xf9beb4d9
24 | },
25 | Msg: {
26 | magicNum: 0xf9beb4d9,
27 | versionBytesNum: 70012 // as of Bitcoin Core v0.12.0
28 | },
29 | PrivKey: {
30 | versionByteNum: 0x80
31 | },
32 | StealthAddress: {
33 | versionByteNum: 42
34 | },
35 | TxBuilder: {
36 | feePerKbNum: 0.0001e8,
37 | dustNum: 546
38 | }
39 | }
40 |
41 | Constants.Testnet = Object.assign({}, Constants.Mainnet, {
42 | Address: {
43 | pubKeyHash: 0x6f,
44 | scriptHash: 0xc4
45 | },
46 | Bip32: {
47 | pubKey: 0x043587cf,
48 | privKey: 0x04358394
49 | },
50 | Block: {
51 | maxNBits: 0x1d00ffff,
52 | magicNum: 0x0b110907
53 | },
54 | Msg: {
55 | magicNum: 0x0b110907,
56 | versionBytesNum: 70012 // as of Bitcoin Core v0.12.0
57 | },
58 | Network: {
59 | maxconnections: 20,
60 | minconnections: 8,
61 | port: 8333,
62 | rendezvous: {
63 | host: 'localhost',
64 | port: 3000,
65 | path: '/'
66 | }
67 | },
68 | PrivKey: {
69 | versionByteNum: 0xef
70 | },
71 | StealthAddress: {
72 | versionByteNum: 43
73 | }
74 | })
75 |
76 | Constants.Regtest = Object.assign({}, Constants.Mainnet, {
77 | Network: {
78 | maxconnections: 20,
79 | minconnections: 8,
80 | port: 18444,
81 | rendezvous: {
82 | host: 'localhost',
83 | port: 3000,
84 | path: '/'
85 | }
86 | }
87 | })
88 |
89 | /**
90 | * Yours Bitcoin can be globally configured to mainnet, testnet, or regtest. Via the
91 | * inject pattern, you always have access to the other networks at any time.
92 | * However, it is very convenient to be able to change the default
93 | * configuration. The default is mainnet, which can be changed to testnet or
94 | * regtest.
95 | */
96 | if (process.env.YOURS_BITCOIN_NETWORK === 'testnet') {
97 | Constants.Default = Object.assign({}, Constants.Testnet)
98 | } else if (process.env.YOURS_BITCOIN_NETWORK === 'regtest') {
99 | Constants.Default = Object.assign({}, Constants.Regtest)
100 | } else {
101 | process.env.YOURS_BITCOIN_NETWORK = 'mainnet'
102 | Constants.Default = Object.assign({}, Constants.Mainnet)
103 | }
104 |
--------------------------------------------------------------------------------
/lib/ecies.js:
--------------------------------------------------------------------------------
1 | /** Ecies (experimental)
2 | * =====================
3 | * http://en.wikipedia.org/wiki/Integrated_Encryption_Scheme
4 | */
5 | 'use strict'
6 | let dependencies = {
7 | Aescbc: require('./aescbc'),
8 | cmp: require('./cmp'),
9 | Hash: require('./hash'),
10 | KeyPair: require('./key-pair'),
11 | Point: require('./point'),
12 | PubKey: require('./pub-key'),
13 | Random: require('./random'),
14 | Workers: require('./workers'),
15 | asink: require('asink')
16 | }
17 |
18 | let inject = function (deps) {
19 | let Aescbc = deps.Aescbc
20 | let cmp = deps.cmp
21 | let Hash = deps.Hash
22 | let KeyPair = deps.KeyPair
23 | let Point = deps.Point
24 | let PubKey = deps.PubKey
25 | let Random = deps.Random
26 | let Workers = deps.Workers
27 | let asink = deps.asink
28 |
29 | let Ecies = {}
30 |
31 | Ecies.encrypt = function (messageBuf, toPubKey, fromKeyPair, ivBuf) {
32 | if (!fromKeyPair) {
33 | fromKeyPair = KeyPair.fromRandom()
34 | }
35 | let r = fromKeyPair.privKey.bn
36 | let RPubKey = fromKeyPair.pubKey
37 | let RBuf = RPubKey.toDer(true)
38 | let KB = toPubKey.point
39 | let P = KB.mul(r)
40 | let S = P.getX()
41 | let Sbuf = S.toBuffer({size: 32})
42 | let kEkM = Hash.sha512(Sbuf)
43 | let kE = kEkM.slice(0, 32)
44 | let kM = kEkM.slice(32, 64)
45 | let c = Aescbc.encrypt(messageBuf, kE, ivBuf)
46 | let d = Hash.sha256Hmac(c, kM)
47 | let encBuf = Buffer.concat([RBuf, c, d])
48 | return encBuf
49 | }
50 |
51 | Ecies.asyncEncrypt = function (messageBuf, toPubKey, fromKeyPair, ivBuf) {
52 | return asink(function * () {
53 | if (!fromKeyPair) {
54 | fromKeyPair = yield KeyPair.asyncFromRandom()
55 | }
56 | if (!ivBuf) {
57 | ivBuf = Random.getRandomBuffer(128 / 8)
58 | }
59 | let args = [messageBuf, toPubKey, fromKeyPair, ivBuf]
60 | let workersResult = yield Workers.asyncClassMethod('Ecies', 'encrypt', args)
61 | return workersResult.resbuf
62 | }, this)
63 | }
64 |
65 | Ecies.decrypt = function (encBuf, toPrivKey) {
66 | let kB = toPrivKey.bn
67 | let fromPubKey = PubKey.fromDer(encBuf.slice(0, 33))
68 | let R = fromPubKey.point
69 | let P = R.mul(kB)
70 | if (P.eq(new Point())) {
71 | throw new Error('P equals 0')
72 | }
73 | let S = P.getX()
74 | let Sbuf = S.toBuffer({size: 32})
75 | let kEkM = Hash.sha512(Sbuf)
76 | let kE = kEkM.slice(0, 32)
77 | let kM = kEkM.slice(32, 64)
78 | let c = encBuf.slice(33, encBuf.length - 32)
79 | let d = encBuf.slice(encBuf.length - 32, encBuf.length)
80 | let d2 = Hash.sha256Hmac(c, kM)
81 | if (!cmp(d, d2)) {
82 | throw new Error('Invalid checksum')
83 | }
84 | let messageBuf = Aescbc.decrypt(c, kE)
85 | return messageBuf
86 | }
87 |
88 | Ecies.asyncDecrypt = function (encBuf, toPrivKey) {
89 | return asink(function * () {
90 | let args = [encBuf, toPrivKey]
91 | let workersResult = yield Workers.asyncClassMethod('Ecies', 'decrypt', args)
92 | return workersResult.resbuf
93 | }, this)
94 | }
95 |
96 | return Ecies
97 | }
98 |
99 | inject = require('injecter')(inject, dependencies)
100 | let Ecies = inject()
101 | Ecies.Mainnet = inject({
102 | KeyPair: require('./key-pair').Mainnet
103 | })
104 | Ecies.Testnet = inject({
105 | KeyPair: require('./key-pair').Testnet
106 | })
107 | module.exports = Ecies
108 |
--------------------------------------------------------------------------------
/lib/get-blocks.js:
--------------------------------------------------------------------------------
1 | /**
2 | * GetBlocks
3 | * =========
4 | *
5 | * The data structure used inside the "getblocks" p2p message. Contains a list
6 | * of block header haashes to be gotten.
7 | */
8 | 'use strict'
9 | let dependencies = {
10 | Bw: require('./bw'),
11 | Constants: require('./constants').Default,
12 | Struct: require('./struct'),
13 | VarInt: require('./var-int')
14 | }
15 |
16 | let inject = function (deps) {
17 | let Bw = deps.Bw
18 | let Constants = deps.Constants
19 | let Struct = deps.Struct
20 | let VarInt = deps.VarInt
21 |
22 | class GetBlocks extends Struct {
23 | constructor (versionBytesNum = Constants.Msg.versionBytesNum, hashBufsVi, hashBufs, stopHashBuf) {
24 | super({versionBytesNum, hashBufsVi, hashBufs, stopHashBuf})
25 | }
26 |
27 | toBw (bw) {
28 | if (!bw) {
29 | bw = new Bw()
30 | }
31 | bw.writeUInt32LE(this.versionBytesNum)
32 | bw.write(this.hashBufsVi.buf)
33 | for (let i = 0; i < this.hashBufs.lenth; i++) {
34 | bw.write(this.hashBufs[i])
35 | }
36 | bw.write(this.stopHashBuf)
37 | return bw
38 | }
39 |
40 | fromBr (br) {
41 | this.versionBytesNum = br.readUInt32LE()
42 | this.hashBufsVi = new VarInt(br.readVarIntBuf())
43 | let len = this.hashBufsVi.toNumber()
44 | this.hashBufs = []
45 | for (let i = 0; i < len; i++) {
46 | this.hashBufs.push(br.read(32))
47 | }
48 | this.stopHashBuf = br.read(32)
49 | return this
50 | }
51 |
52 | /**
53 | * The last hashBuf in the list is the stopHashBuf.
54 | */
55 | fromHashes (hashBufs) {
56 | if (hashBufs.length < 1) {
57 | throw new Error('hashBufs must have at least one buffer, the stopHashBuf')
58 | }
59 | this.hashBufsVi = new VarInt().fromNumber(hashBufs.length - 1)
60 | this.hashBufs = hashBufs.slice(0, hashBufs.length - 1)
61 | this.stopHashBuf = hashBufs[hashBufs.length - 1]
62 | return this
63 | }
64 |
65 | static fromHashes (hashBufs) {
66 | return new this().fromHashes(hashBufs)
67 | }
68 |
69 | toHashes () {
70 | return this.hashBufs.concat(this.stopHashBuf)
71 | }
72 | }
73 |
74 | return GetBlocks
75 | }
76 |
77 | inject = require('injecter')(inject, dependencies)
78 | let GetBlocks = inject()
79 | module.exports = GetBlocks
80 |
--------------------------------------------------------------------------------
/lib/inv.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Inv
3 | * ===
4 | *
5 | * Inventory - used in p2p messages.
6 | */
7 | 'use strict'
8 | let dependencies = {
9 | Bw: require('./bw'),
10 | Struct: require('./struct')
11 | }
12 |
13 | let inject = function (deps) {
14 | let Bw = deps.Bw
15 | let Struct = deps.Struct
16 |
17 | class Inv extends Struct {
18 | constructor (typeNum, hashBuf) {
19 | super({typeNum, hashBuf})
20 | }
21 |
22 | fromBr (br) {
23 | this.typeNum = br.readUInt32LE()
24 | this.hashBuf = br.read(32)
25 | return this
26 | }
27 |
28 | toBw (bw) {
29 | if (!bw) {
30 | bw = new Bw()
31 | }
32 | bw.writeUInt32LE(this.typeNum)
33 | bw.write(this.hashBuf)
34 | return bw
35 | }
36 |
37 | isTx () {
38 | return this.typeNum === Inv.MSG_TX
39 | }
40 |
41 | isBlock () {
42 | return this.typeNum === Inv.MSG_BLOCK
43 | }
44 |
45 | isFilteredBlock () {
46 | return this.typeNum === Inv.MSG_FILTERED_BLOCK
47 | }
48 | }
49 |
50 | Inv.MSG_TX = 1
51 | Inv.MSG_BLOCK = 2
52 | Inv.MSG_FILTERED_BLOCK = 3
53 |
54 | return Inv
55 | }
56 |
57 | inject = require('injecter')(inject, dependencies)
58 | let Inv = inject()
59 | module.exports = Inv
60 |
--------------------------------------------------------------------------------
/lib/kdf.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Kdf
3 | * ===
4 | *
5 | * Kdf stands for "key derivation function". A key derivation function is a
6 | * function that converts random data into a properly formatted key that can be
7 | * used by a cryptographic function. The one you probably want to use is
8 | * Pbkdf2, although various other ones are provided as a convenience.
9 | */
10 | 'use strict'
11 | let dependencies = {
12 | Bn: require('./bn'),
13 | Hash: require('./hash'),
14 | KeyPair: require('./key-pair'),
15 | pbkdf2: require('pbkdf2-compat'),
16 | Point: require('./point'),
17 | PrivKey: require('./priv-key')
18 | }
19 |
20 | let inject = function (deps) {
21 | let Bn = deps.Bn
22 | let Hash = deps.Hash
23 | let KeyPair = deps.KeyPair
24 | let pbkdf2 = deps.pbkdf2
25 | let Point = deps.Point
26 | let PrivKey = deps.PrivKey
27 |
28 | let Kdf = {}
29 |
30 | // Pbkdf2
31 | // http://tools.ietf.org/html/rfc2898#section-5.2
32 | // http://en.wikipedia.org/wiki/Pbkdf2
33 | Kdf.Pbkdf2 = function (passBuf, saltBuf, nIterations, keyLenBits, hashFStr) {
34 | if (!nIterations) {
35 | nIterations = 1
36 | }
37 | if (!keyLenBits) {
38 | keyLenBits = 512
39 | }
40 | if (!hashFStr) {
41 | hashFStr = 'sha512'
42 | }
43 | return pbkdf2.pbkdf2Sync(passBuf, saltBuf, nIterations, keyLenBits / 8, hashFStr)
44 | }
45 |
46 | Kdf.buf2KeyPair = function (buf) {
47 | return Kdf.sha256Hmac2KeyPair(buf)
48 | }
49 |
50 | Kdf.sha256Hmac2KeyPair = function (buf) {
51 | let privKey = Kdf.sha256Hmac2PrivKey(buf)
52 | let keyPair = new KeyPair().fromPrivKey(privKey)
53 | return keyPair
54 | }
55 |
56 | Kdf.sha256Hmac2PrivKey = function (buf) {
57 | let bn, hash
58 | let concat = new Buffer([])
59 | do {
60 | hash = Hash.sha256Hmac(buf, concat)
61 | bn = new Bn().fromBuffer(hash)
62 | concat = Buffer.concat([concat, new Buffer(0)])
63 | } while (!bn.lt(Point.getN()))
64 | return new PrivKey().fromBn(bn)
65 | }
66 |
67 | return Kdf
68 | }
69 |
70 | inject = require('injecter')(inject, dependencies)
71 | let Kdf = inject()
72 | Kdf.Mainnet = inject({
73 | KeyPair: require('./key-pair').Mainnet,
74 | PrivKey: require('./priv-key').Mainnet
75 | })
76 | Kdf.Testnet = inject({
77 | KeyPair: require('./key-pair').Testnet,
78 | PrivKey: require('./priv-key').Testnet
79 | })
80 | module.exports = Kdf
81 |
--------------------------------------------------------------------------------
/lib/key-pair.js:
--------------------------------------------------------------------------------
1 | /**
2 | * KeyPair
3 | * =======
4 | *
5 | * A keyPair is a collection of a private key and a public key.
6 | * let keyPair = new KeyPair().fromRandom()
7 | * let keyPair = new KeyPair().fromPrivKey(privKey)
8 | * let privKey = keyPair.privKey
9 | * let pubKey = keyPair.pubKey
10 | */
11 | 'use strict'
12 | let dependencies = {
13 | PrivKey: require('./priv-key'),
14 | PubKey: require('./pub-key'),
15 | Struct: require('./struct'),
16 | Bw: require('./bw'),
17 | asink: require('asink')
18 | }
19 |
20 | let inject = function (deps) {
21 | let PrivKey = deps.PrivKey
22 | let PubKey = deps.PubKey
23 | let Struct = deps.Struct
24 | let Bw = deps.Bw
25 | let asink = deps.asink
26 |
27 | class KeyPair extends Struct {
28 | constructor (privKey, pubKey) {
29 | super({privKey, pubKey})
30 | }
31 |
32 | fromJSON (json) {
33 | if (json.privKey) {
34 | this.privKey = PrivKey.fromJSON(json.privKey)
35 | }
36 | if (json.pubKey) {
37 | this.pubKey = PubKey.fromJSON(json.pubKey)
38 | }
39 | return this
40 | }
41 | /*
42 | toJSON () {
43 | let json = {}
44 | if (this.privKey && this.privKey !== undefined) {
45 | json.privKey = this.privKey.toJSON()
46 | }
47 | if (this.pubKey && this.pubKey !== undefined) {
48 | json.pubKey = this.pubKey.toJSON()
49 | }
50 | return json
51 | }
52 | */
53 | fromBr (br) {
54 | let buflen1 = br.readUInt8()
55 | if (buflen1 > 0) {
56 | this.privKey = new PrivKey().fromFastBuffer(br.read(buflen1))
57 | }
58 | let buflen2 = br.readUInt8()
59 | if (buflen2 > 0) {
60 | this.pubKey = new PubKey().fromFastBuffer(br.read(buflen2))
61 | }
62 | return this
63 | }
64 |
65 | toBw (bw) {
66 | if (!bw) {
67 | bw = new Bw()
68 | }
69 | if (this.privKey) {
70 | let privKeybuf = this.privKey.toFastBuffer()
71 | bw.writeUInt8(privKeybuf.length)
72 | bw.write(privKeybuf)
73 | } else {
74 | bw.writeUInt8(0)
75 | }
76 | if (this.pubKey) {
77 | let pubKeybuf = this.pubKey.toFastBuffer()
78 | bw.writeUInt8(pubKeybuf.length)
79 | bw.write(pubKeybuf)
80 | } else {
81 | bw.writeUInt8(0)
82 | }
83 | return bw
84 | }
85 |
86 | fromString (str) {
87 | return this.fromJSON(JSON.parse(str))
88 | }
89 |
90 | toString () {
91 | return JSON.stringify(this.toJSON())
92 | }
93 |
94 | toPublic () {
95 | let keyPair = new KeyPair().fromObject(this)
96 | keyPair.privKey = undefined
97 | return keyPair
98 | }
99 |
100 | fromPrivKey (privKey) {
101 | this.privKey = privKey
102 | this.pubKey = new PubKey().fromPrivKey(privKey)
103 | return this
104 | }
105 |
106 | static fromPrivKey (privKey) {
107 | return new this().fromPrivKey(privKey)
108 | }
109 |
110 | asyncFromPrivKey (privKey) {
111 | return asink(function * () {
112 | this.privKey = privKey
113 | this.pubKey = yield new PubKey().asyncFromPrivKey(privKey)
114 | return this
115 | }, this)
116 | }
117 |
118 | static asyncFromPrivKey (privKey) {
119 | return new this().asyncFromPrivKey(privKey)
120 | }
121 |
122 | fromRandom () {
123 | this.privKey = new PrivKey().fromRandom()
124 | this.pubKey = new PubKey().fromPrivKey(this.privKey)
125 | return this
126 | }
127 |
128 | static fromRandom () {
129 | return new this().fromRandom()
130 | }
131 |
132 | asyncFromRandom () {
133 | return asink(function * () {
134 | this.privKey = new PrivKey().fromRandom()
135 | return this.asyncFromPrivKey(this.privKey)
136 | }, this)
137 | }
138 |
139 | static asyncFromRandom () {
140 | return new this().asyncFromRandom()
141 | }
142 | }
143 |
144 | return KeyPair
145 | }
146 |
147 | inject = require('injecter')(inject, dependencies)
148 | let KeyPair = inject()
149 | KeyPair.Mainnet = inject({
150 | PrivKey: require('./priv-key').Mainnet
151 | })
152 | KeyPair.Testnet = inject({
153 | PrivKey: require('./priv-key').Testnet
154 | })
155 | module.exports = KeyPair
156 |
--------------------------------------------------------------------------------
/lib/merkle.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Merkle
3 | * ======
4 | *
5 | * A node in a Merkle tree (possibly the root node, in which case it is the
6 | * Merkle root). A node either contains a buffer or links to two other nodes.
7 | */
8 | 'use strict'
9 |
10 | let dependencies = {
11 | Hash: require('./hash'),
12 | Struct: require('./struct')
13 | }
14 |
15 | let inject = function (deps) {
16 | let Hash = deps.Hash
17 | let Struct = deps.Struct
18 |
19 | class Merkle extends Struct {
20 | constructor (hashBuf, buf, merkle1, merkle2) {
21 | super({hashBuf, buf, merkle1, merkle2})
22 | }
23 |
24 | hash () {
25 | if (this.hashBuf) {
26 | return this.hashBuf
27 | }
28 | if (this.buf) {
29 | return Hash.sha256Sha256(this.buf)
30 | }
31 | let hashBuf1 = this.merkle1.hash()
32 | let hashBuf2 = this.merkle2.hash()
33 | this.buf = Buffer.concat([hashBuf1, hashBuf2])
34 | return Hash.sha256Sha256(this.buf)
35 | }
36 |
37 | fromBuffers (bufs) {
38 | if (bufs.length < 1) {
39 | throw new Error('buffers must have a length')
40 | }
41 | bufs = bufs.slice()
42 | let log = Math.log2(bufs.length)
43 | if (!Number.isInteger(log)) {
44 | // If a merkle tree does not have a number of ends that is a power of 2,
45 | // then we have to copy the last value until it is a power of 2. Note
46 | // that we copy *the actual object* over and over again, which ensures
47 | // that when we finds its hash, the hash is cached.
48 | let lastval = bufs[bufs.length - 1]
49 | var len = Math.pow(2, Math.ceil(log))
50 | for (let i = bufs.length; i < len; i++) {
51 | bufs.push(lastval)
52 | }
53 | }
54 | let bufs1 = bufs.slice(0, bufs.length / 2)
55 | let bufs2 = bufs.slice(bufs.length / 2)
56 | this.fromBufferArrays(bufs1, bufs2)
57 | return this
58 | }
59 |
60 | static fromBuffers (bufs) {
61 | return new this().fromBuffers(bufs)
62 | }
63 |
64 | /**
65 | * Takes two arrays, both of which *must* be of a length that is a power of
66 | * two.
67 | */
68 | fromBufferArrays (bufs1, bufs2) {
69 | if (bufs1.length === 1) {
70 | this.merkle1 = new Merkle(undefined, bufs1[0])
71 | this.merkle2 = new Merkle(undefined, bufs2[0])
72 | return this
73 | }
74 | let bufs11 = bufs1.slice(0, bufs1.length / 2)
75 | let bufs12 = bufs1.slice(bufs1.length / 2)
76 | this.merkle1 = new Merkle().fromBufferArrays(bufs11, bufs12)
77 | let bufs21 = bufs2.slice(0, bufs2.length / 2)
78 | let bufs22 = bufs2.slice(bufs2.length / 2)
79 | this.merkle2 = new Merkle().fromBufferArrays(bufs21, bufs22)
80 | return this
81 | }
82 |
83 | static fromBufferArrays (bufs1, bufs2) {
84 | return new this().fromBufferArrays(bufs1, bufs2)
85 | }
86 |
87 | leavesNum () {
88 | if (this.merkle1) {
89 | return this.merkle1.leavesNum() + this.merkle2.leavesNum()
90 | }
91 | if (this.buf) {
92 | return 1
93 | }
94 | throw new Error('invalid number of leaves')
95 | }
96 | }
97 |
98 | return Merkle
99 | }
100 |
101 | inject = require('injecter')(inject, dependencies)
102 | let Merkle = inject()
103 | module.exports = Merkle
104 |
--------------------------------------------------------------------------------
/lib/msg-addr.js:
--------------------------------------------------------------------------------
1 | /**
2 | * MsgAddr
3 | * ======
4 | *
5 | * Sends a a list of addrs (IP addresses) of nodes we are connected to.
6 | */
7 | 'use strict'
8 | let dependencies = {
9 | Addr: require('./addr'),
10 | Br: require('./br'),
11 | Bw: require('./bw'),
12 | Msg: require('./msg')
13 | }
14 |
15 | let inject = function (deps) {
16 | let Addr = deps.Addr
17 | let Br = deps.Br
18 | let Bw = deps.Bw
19 | let Msg = deps.Msg
20 |
21 | class MsgAddr extends Msg {
22 | initialize () {
23 | Msg.prototype.initialize.call(this)
24 | this.setCmd('addr')
25 | return this
26 | }
27 |
28 | static dataBufFromAddrs (addrs) {
29 | let bw = new Bw()
30 | bw.writeVarIntNum(addrs.length)
31 | for (let i = 0; i < addrs.length; i++) {
32 | bw.write(addrs[i].toBuffer())
33 | }
34 | return bw.toBuffer()
35 | }
36 |
37 | fromAddrs (addrs) {
38 | this.setData(MsgAddr.dataBufFromAddrs(addrs))
39 | return this
40 | }
41 |
42 | static fromAddrs (addrs) {
43 | return new this().fromAddrs(addrs)
44 | }
45 |
46 | asyncFromAddrs (addrs) {
47 | return this.asyncSetData(MsgAddr.dataBufFromAddrs(addrs))
48 | }
49 |
50 | static asyncFromAddrs (addrs) {
51 | return new this().asyncFromAddrs(addrs)
52 | }
53 |
54 | toAddrs () {
55 | let br = new Br(this.dataBuf)
56 | let len = br.readVarIntNum()
57 | let addrs = []
58 | for (let i = 0; i < len; i++) {
59 | let addrbuf = br.read(4 + 8 + 16 + 2)
60 | let addr = new Addr().fromBuffer(addrbuf)
61 | addrs.push(addr)
62 | }
63 | return addrs
64 | }
65 |
66 | isValid () {
67 | return this.getCmd() === 'addr'
68 | }
69 | }
70 |
71 | return MsgAddr
72 | }
73 |
74 | inject = require('injecter')(inject, dependencies)
75 | let MsgAddr = inject()
76 | MsgAddr.Mainnet = inject({
77 | Msg: require('./msg').Mainnet
78 | })
79 | MsgAddr.Testnet = inject({
80 | Msg: require('./msg').Testnet
81 | })
82 | module.exports = MsgAddr
83 |
--------------------------------------------------------------------------------
/lib/msg-alert.js:
--------------------------------------------------------------------------------
1 | /**
2 | * MsgAlert
3 | * ======
4 | *
5 | * An alert sent across the network by a developer with access to a primary
6 | * private key. Since this message type is almost entirely unused and will be
7 | * removed from bitcoin soon, it is not fully implemented here.
8 | */
9 | 'use strict'
10 | let dependencies = {
11 | Msg: require('./msg')
12 | }
13 |
14 | let inject = function (deps) {
15 | let Msg = deps.Msg
16 |
17 | class MsgAlert extends Msg {
18 | initialize () {
19 | Msg.prototype.initialize.call(this)
20 | this.setCmd('alert')
21 | return this
22 | }
23 |
24 | isValid () {
25 | return this.getCmd() === 'alert'
26 | }
27 | }
28 |
29 | return MsgAlert
30 | }
31 |
32 | inject = require('injecter')(inject, dependencies)
33 | let MsgAlert = inject()
34 | MsgAlert.Mainnet = inject({
35 | Msg: require('./msg').Mainnet
36 | })
37 | MsgAlert.Testnet = inject({
38 | Msg: require('./msg').Testnet
39 | })
40 | module.exports = MsgAlert
41 |
--------------------------------------------------------------------------------
/lib/msg-block.js:
--------------------------------------------------------------------------------
1 | /**
2 | * MsgBlock
3 | * ========
4 | *
5 | * Sends one block.
6 | */
7 | 'use strict'
8 | let dependencies = {
9 | Block: require('./block'),
10 | Msg: require('./msg')
11 | }
12 |
13 | let inject = function (deps) {
14 | let Block = deps.Block
15 | let Msg = deps.Msg
16 |
17 | class MsgBlock extends Msg {
18 | initialize () {
19 | Msg.prototype.initialize.call(this)
20 | this.setCmd('block')
21 | return this
22 | }
23 |
24 | fromBlock (block) {
25 | this.setData(block.toBuffer())
26 | return this
27 | }
28 |
29 | static fromBlock (block) {
30 | return new this().fromBlock(block)
31 | }
32 |
33 | asyncFromBlock (block) {
34 | return this.asyncSetData(block.toBuffer())
35 | }
36 |
37 | static asyncFromBlock (block) {
38 | return new this().asyncFromBlock(block)
39 | }
40 |
41 | toBlock () {
42 | return new Block().fromBuffer(this.dataBuf)
43 | }
44 |
45 | isValid () {
46 | return this.getCmd() === 'block'
47 | }
48 | }
49 |
50 | return MsgBlock
51 | }
52 |
53 | inject = require('injecter')(inject, dependencies)
54 | let MsgBlock = inject()
55 | MsgBlock.Mainnet = inject({
56 | Block: require('./block').Mainnet,
57 | Msg: require('./msg').Mainnet
58 | })
59 | MsgBlock.Testnet = inject({
60 | Block: require('./block').Testnet,
61 | Msg: require('./msg').Testnet
62 | })
63 | module.exports = MsgBlock
64 |
--------------------------------------------------------------------------------
/lib/msg-get-addr.js:
--------------------------------------------------------------------------------
1 | /**
2 | * MsgGetAddr
3 | * ==========
4 | *
5 | * Requests an addr message. This message has no data (dataBuf), and as such is
6 | * very simple.
7 | */
8 | 'use strict'
9 | let dependencies = {
10 | Msg: require('./msg')
11 | }
12 |
13 | let inject = function (deps) {
14 | let Msg = deps.Msg
15 |
16 | class MsgGetAddr extends Msg {
17 | initialize () {
18 | Msg.prototype.initialize.call(this)
19 | this.setCmd('getaddr')
20 | this.datasize = 0
21 | this.dataBuf = new Buffer(0)
22 | this.checksumbuf = new Buffer('5df6e0e2', 'hex')
23 | return this
24 | }
25 |
26 | isValid () {
27 | return this.getCmd() === 'getaddr' && this.dataBuf.length === 0
28 | }
29 | }
30 |
31 | return MsgGetAddr
32 | }
33 |
34 | inject = require('injecter')(inject, dependencies)
35 | let MsgGetAddr = inject()
36 | MsgGetAddr.Mainnet = inject({
37 | Msg: require('./msg').Mainnet
38 | })
39 | MsgGetAddr.Testnet = inject({
40 | Msg: require('./msg').Testnet
41 | })
42 | module.exports = MsgGetAddr
43 |
--------------------------------------------------------------------------------
/lib/msg-get-blocks.js:
--------------------------------------------------------------------------------
1 | /**
2 | * MsgGetBlocks
3 | * ============
4 | *
5 | * Gets what blocks are available from a given peer.
6 | */
7 | 'use strict'
8 | let dependencies = {
9 | GetBlocks: require('./get-blocks'),
10 | Msg: require('./msg'),
11 | asink: require('asink')
12 | }
13 |
14 | let inject = function (deps) {
15 | let GetBlocks = deps.GetBlocks
16 | let Msg = deps.Msg
17 | let asink = deps.asink
18 |
19 | class MsgGetBlocks extends Msg {
20 | initialize () {
21 | Msg.prototype.initialize.call(this)
22 | this.setCmd('getblocks')
23 | return this
24 | }
25 |
26 | fromGetBlocks (getblocks) {
27 | return this.setData(getblocks.toBuffer())
28 | }
29 |
30 | static fromGetBlocks (getblocks) {
31 | return new this().fromGetBlocks(getblocks)
32 | }
33 |
34 | fromHashes (hashes) {
35 | let getblocks = new GetBlocks().fromHashes(hashes)
36 | return this.fromGetBlocks(getblocks)
37 | }
38 |
39 | static fromHashes (hashes) {
40 | return new this().fromHashes(hashes)
41 | }
42 |
43 | asyncFromGetBlocks (getblocks) {
44 | return this.asyncSetData(getblocks.toBuffer())
45 | }
46 |
47 | static asyncFromGetBlocks (getblocks) {
48 | return new this().asyncFromGetBlocks(getblocks)
49 | }
50 |
51 | asyncFromHashes (hashes) {
52 | return asink(function * () {
53 | let getblocks = new GetBlocks().fromHashes(hashes)
54 | return this.asyncFromGetBlocks(getblocks)
55 | }, this)
56 | }
57 |
58 | static asyncFromHashes (hashes) {
59 | return new this().asyncFromHashes(hashes)
60 | }
61 |
62 | toGetBlocks () {
63 | return new GetBlocks().fromBuffer(this.dataBuf)
64 | }
65 |
66 | toHashes () {
67 | return new GetBlocks().fromBuffer(this.dataBuf).toHashes()
68 | }
69 |
70 | isValid () {
71 | return this.getCmd() === 'getblocks'
72 | }
73 | }
74 |
75 | return MsgGetBlocks
76 | }
77 |
78 | inject = require('injecter')(inject, dependencies)
79 | let MsgGetBlocks = inject()
80 | MsgGetBlocks.Mainnet = inject({
81 | Block: require('./block').Mainnet,
82 | Msg: require('./msg').Mainnet
83 | })
84 | MsgGetBlocks.Testnet = inject({
85 | Block: require('./block').Testnet,
86 | Msg: require('./msg').Testnet
87 | })
88 | module.exports = MsgGetBlocks
89 |
--------------------------------------------------------------------------------
/lib/msg-get-data.js:
--------------------------------------------------------------------------------
1 | /**
2 | * MsgGetData
3 | * ==========
4 | *
5 | * This is identical to MsgInv, except the command is "getdata", and it is used
6 | * in slightly different cases. As such as simply inherit from MsgInv.
7 | */
8 | 'use strict'
9 | let dependencies = {
10 | MsgInv: require('./msg-inv')
11 | }
12 |
13 | let inject = function (deps) {
14 | let MsgInv = deps.MsgInv
15 |
16 | class MsgGetData extends MsgInv {
17 | initialize () {
18 | MsgInv.prototype.initialize.call(this)
19 | this.setCmd('getdata')
20 | return this
21 | }
22 |
23 | isValid () {
24 | return this.getCmd() === 'getdata'
25 | }
26 | }
27 |
28 | return MsgGetData
29 | }
30 |
31 | inject = require('injecter')(inject, dependencies)
32 | let MsgGetData = inject()
33 | MsgGetData.Mainnet = inject({
34 | MsgInv: require('./msg-inv').Mainnet
35 | })
36 | MsgGetData.Testnet = inject({
37 | MsgInv: require('./msg-inv').Testnet
38 | })
39 | module.exports = MsgGetData
40 |
--------------------------------------------------------------------------------
/lib/msg-get-headers.js:
--------------------------------------------------------------------------------
1 | /**
2 | * MsgGetHeaders
3 | * =============
4 | *
5 | * This is identical to MsgGetBlocks, except the command is "getheaders", and
6 | * it is used in slightly different cases. As such as simply inherit from
7 | * MsgGetBlocks.
8 | */
9 | 'use strict'
10 | let dependencies = {
11 | MsgGetBlocks: require('./msg-get-blocks')
12 | }
13 |
14 | let inject = function (deps) {
15 | let MsgGetBlocks = deps.MsgGetBlocks
16 |
17 | function MsgGetHeaders (magicNum, cmdbuf, datasize, checksumbuf, dataBuf) {
18 | if (!(this instanceof MsgGetHeaders)) {
19 | return new MsgGetHeaders(magicNum, cmdbuf, datasize, checksumbuf, dataBuf)
20 | }
21 | this.initialize()
22 | this.fromObject({magicNum, cmdbuf, datasize, checksumbuf, dataBuf})
23 | }
24 |
25 | MsgGetHeaders.prototype = Object.create(MsgGetBlocks.prototype)
26 | MsgGetHeaders.prototype.constructor = MsgGetHeaders
27 |
28 | MsgGetHeaders.prototype.initialize = function () {
29 | MsgGetBlocks.prototype.initialize.call(this)
30 | this.setCmd('getheaders')
31 | return this
32 | }
33 |
34 | MsgGetHeaders.prototype.isValid = function () {
35 | return this.getCmd() === 'getheaders'
36 | }
37 |
38 | return MsgGetHeaders
39 | }
40 |
41 | inject = require('injecter')(inject, dependencies)
42 | let MsgGetHeaders = inject()
43 | MsgGetHeaders.Mainnet = inject({
44 | MsgGetBlocks: require('./msg-get-blocks').Mainnet
45 | })
46 | MsgGetHeaders.Testnet = inject({
47 | MsgGetBlocks: require('./msg-get-blocks').Testnet
48 | })
49 | module.exports = MsgGetHeaders
50 |
--------------------------------------------------------------------------------
/lib/msg-headers.js:
--------------------------------------------------------------------------------
1 | /**
2 | * MsgHeaders
3 | * ==========
4 | *
5 | * Sends a list of block headers.
6 | */
7 | 'use strict'
8 | let dependencies = {
9 | BlockHeader: require('./block-header'),
10 | Br: require('./br'),
11 | Bw: require('./bw'),
12 | Msg: require('./msg')
13 | }
14 |
15 | let inject = function (deps) {
16 | let BlockHeader = deps.BlockHeader
17 | let Br = deps.Br
18 | let Bw = deps.Bw
19 | let Msg = deps.Msg
20 |
21 | class MsgHeaders extends Msg {
22 | initialize () {
23 | Msg.prototype.initialize.call(this)
24 | this.setCmd('headers')
25 | return this
26 | }
27 |
28 | static dataBufFromBlockHeaders (blockHeaders) {
29 | let bw = new Bw()
30 | bw.writeVarIntNum(blockHeaders.length)
31 | for (let i = 0; i < blockHeaders.length; i++) {
32 | bw.write(blockHeaders[i].toBuffer())
33 | }
34 | return bw.toBuffer()
35 | }
36 |
37 | fromBlockHeaders (blockHeaders) {
38 | this.setData(MsgHeaders.dataBufFromBlockHeaders(blockHeaders))
39 | return this
40 | }
41 |
42 | static fromBlockHeaders (blockHeaders) {
43 | return new this().fromBlockHeaders(blockHeaders)
44 | }
45 |
46 | asyncFromBlockHeaders (blockHeaders) {
47 | return this.asyncSetData(MsgHeaders.dataBufFromBlockHeaders(blockHeaders))
48 | }
49 |
50 | toBlockHeaders () {
51 | let br = new Br(this.dataBuf)
52 | let len = br.readVarIntNum()
53 | let blockHeaders = []
54 | for (let i = 0; i < len; i++) {
55 | let blockHeaderbuf = br.read(80)
56 | let blockHeader = new BlockHeader().fromBuffer(blockHeaderbuf)
57 | blockHeaders.push(blockHeader)
58 | }
59 | return blockHeaders
60 | }
61 |
62 | isValid () {
63 | return this.getCmd() === 'headers'
64 | }
65 | }
66 |
67 | return MsgHeaders
68 | }
69 |
70 | inject = require('injecter')(inject, dependencies)
71 | let MsgHeaders = inject()
72 | MsgHeaders.Mainnet = inject({
73 | Msg: require('./msg').Mainnet
74 | })
75 | MsgHeaders.Testnet = inject({
76 | Msg: require('./msg').Testnet
77 | })
78 | module.exports = MsgHeaders
79 |
--------------------------------------------------------------------------------
/lib/msg-inv.js:
--------------------------------------------------------------------------------
1 | /**
2 | * MsgInv
3 | * ======
4 | *
5 | * Sends an inventory, or list of "inv" structures, i.e. a list of objects that
6 | * we have.
7 | */
8 | 'use strict'
9 | let dependencies = {
10 | Br: require('./br'),
11 | Bw: require('./bw'),
12 | Inv: require('./inv'),
13 | Msg: require('./msg')
14 | }
15 |
16 | let inject = function (deps) {
17 | let Br = deps.Br
18 | let Bw = deps.Bw
19 | let Inv = deps.Inv
20 | let Msg = deps.Msg
21 |
22 | class MsgInv extends Msg {
23 | initialize () {
24 | Msg.prototype.initialize.call(this)
25 | this.setCmd('inv')
26 | return this
27 | }
28 |
29 | static dataBufFromInvs (invs) {
30 | let bw = new Bw()
31 | bw.writeVarIntNum(invs.length)
32 | for (let i = 0; i < invs.length; i++) {
33 | bw.write(invs[i].toBuffer())
34 | }
35 | return bw.toBuffer()
36 | }
37 |
38 | fromInvs (invs) {
39 | this.setData(MsgInv.dataBufFromInvs(invs))
40 | return this
41 | }
42 |
43 | static fromInvs (invs) {
44 | return new this().fromInvs(invs)
45 | }
46 |
47 | asyncFromInvs (invs) {
48 | return this.asyncSetData(MsgInv.dataBufFromInvs(invs))
49 | }
50 |
51 | static asyncFromInvs (invs) {
52 | return new this().asyncFromInvs(invs)
53 | }
54 |
55 | toInvs () {
56 | let br = new Br(this.dataBuf)
57 | let len = br.readVarIntNum()
58 | let invs = []
59 | for (let i = 0; i < len; i++) {
60 | let invbuf = br.read(4 + 32)
61 | let inv = new Inv().fromBuffer(invbuf)
62 | invs.push(inv)
63 | }
64 | return invs
65 | }
66 |
67 | isValid () {
68 | return this.getCmd() === 'inv'
69 | }
70 | }
71 |
72 | return MsgInv
73 | }
74 |
75 | inject = require('injecter')(inject, dependencies)
76 | let MsgInv = inject()
77 | MsgInv.Mainnet = inject({
78 | Msg: require('./msg').Mainnet
79 | })
80 | MsgInv.Testnet = inject({
81 | Msg: require('./msg').Testnet
82 | })
83 | module.exports = MsgInv
84 |
--------------------------------------------------------------------------------
/lib/msg-mem-pool.js:
--------------------------------------------------------------------------------
1 | /**
2 | * MsgMemPool
3 | * ==========
4 | *
5 | * Requests transactions in the mempool. This message has no data (dataBuf),
6 | * and as such is very simple.
7 | */
8 | 'use strict'
9 | let dependencies = {
10 | Msg: require('./msg')
11 | }
12 |
13 | let inject = function (deps) {
14 | let Msg = deps.Msg
15 |
16 | class MsgMemPool extends Msg {
17 | initialize () {
18 | Msg.prototype.initialize.call(this)
19 | this.setCmd('mempool')
20 | this.datasize = 0
21 | this.dataBuf = new Buffer(0)
22 | this.checksumbuf = new Buffer('5df6e0e2', 'hex')
23 | return this
24 | }
25 |
26 | isValid () {
27 | return this.getCmd() === 'mempool' && this.dataBuf.length === 0
28 | }
29 | }
30 |
31 | return MsgMemPool
32 | }
33 |
34 | inject = require('injecter')(inject, dependencies)
35 | let MsgMemPool = inject()
36 | MsgMemPool.Mainnet = inject({
37 | Msg: require('./msg').Mainnet
38 | })
39 | MsgMemPool.Testnet = inject({
40 | Msg: require('./msg').Testnet
41 | })
42 | module.exports = MsgMemPool
43 |
--------------------------------------------------------------------------------
/lib/msg-not-found.js:
--------------------------------------------------------------------------------
1 | /**
2 | * MsgNotFound
3 | * ===========
4 | *
5 | * Sent when requested data is not found. This is identical to MsgInv, except
6 | * the command is "notfound", and it is used in slightly different cases. As
7 | * such it simply inherits from MsgInv.
8 | */
9 | 'use strict'
10 | let dependencies = {
11 | MsgInv: require('./msg-inv')
12 | }
13 |
14 | let inject = function (deps) {
15 | let MsgInv = deps.MsgInv
16 |
17 | class MsgNotFound extends MsgInv {
18 | initialize () {
19 | MsgInv.prototype.initialize.call(this)
20 | this.setCmd('notfound')
21 | return this
22 | }
23 |
24 | isValid () {
25 | return this.getCmd() === 'notfound'
26 | }
27 | }
28 |
29 | return MsgNotFound
30 | }
31 |
32 | inject = require('injecter')(inject, dependencies)
33 | let MsgNotFound = inject()
34 | MsgNotFound.Mainnet = inject({
35 | MsgInv: require('./msg-inv').Mainnet
36 | })
37 | MsgNotFound.Testnet = inject({
38 | MsgInv: require('./msg-inv').Testnet
39 | })
40 | module.exports = MsgNotFound
41 |
--------------------------------------------------------------------------------
/lib/msg-ping.js:
--------------------------------------------------------------------------------
1 | /**
2 | * MsgPing
3 | * =======
4 | *
5 | * A ping p2p message. This is defined as a msg with command "ping" and where
6 | * dataBuf is a randomly selected 8 byte buffer.
7 | */
8 | 'use strict'
9 | let dependencies = {
10 | Msg: require('./msg'),
11 | Random: require('./random')
12 | }
13 |
14 | let inject = function (deps) {
15 | let Msg = deps.Msg
16 | let Random = deps.Random
17 |
18 | class MsgPing extends Msg {
19 | initialize () {
20 | Msg.prototype.initialize.call(this)
21 | this.setCmd('ping')
22 | return this
23 | }
24 |
25 | fromRandom () {
26 | this.setData(Random.getRandomBuffer(8))
27 | return this
28 | }
29 |
30 | static fromRandom () {
31 | return new this().fromRandom()
32 | }
33 |
34 | asyncFromRandom () {
35 | return this.asyncSetData(Random.getRandomBuffer(8))
36 | }
37 |
38 | static asyncFromRandom () {
39 | return new this().asyncFromRandom()
40 | }
41 |
42 | isValid () {
43 | return this.dataBuf.length === 8 && this.getCmd() === 'ping'
44 | }
45 | }
46 |
47 | return MsgPing
48 | }
49 |
50 | inject = require('injecter')(inject, dependencies)
51 | let MsgPing = inject()
52 | MsgPing.Mainnet = inject({
53 | Msg: require('./msg').Mainnet
54 | })
55 | MsgPing.Testnet = inject({
56 | Msg: require('./msg').Testnet
57 | })
58 | module.exports = MsgPing
59 |
--------------------------------------------------------------------------------
/lib/msg-pong.js:
--------------------------------------------------------------------------------
1 | /**
2 | * MsgPong
3 | * =======
4 | *
5 | * A pong message on the p2p network is a reponse to a ping. A pong is almost
6 | * the same as a ping, in that it contains a randomly selected 8 byte dataBuf.
7 | * The dataBuf is always the same as the ping it is responding to. And also,
8 | * the command is set to "pong" instead of "ping".
9 | */
10 | 'use strict'
11 | let dependencies = {
12 | Msg: require('./msg')
13 | }
14 |
15 | let inject = function (deps) {
16 | let Msg = deps.Msg
17 |
18 | class MsgPong extends Msg {
19 | initialize () {
20 | Msg.prototype.initialize.call(this)
21 | this.setCmd('pong')
22 | return this
23 | }
24 |
25 | fromMsgPing (msgping) {
26 | this.fromObject(msgping)
27 | this.setCmd('pong')
28 | return this
29 | }
30 |
31 | static fromMsgPing (msgping) {
32 | return new this().fromMsgPing(msgping)
33 | }
34 |
35 | isValid () {
36 | return this.dataBuf.length === 8 && this.getCmd() === 'pong'
37 | }
38 | }
39 |
40 | return MsgPong
41 | }
42 |
43 | inject = require('injecter')(inject, dependencies)
44 | let MsgPong = inject()
45 | MsgPong.Mainnet = inject({
46 | Msg: require('./msg').Mainnet
47 | })
48 | MsgPong.Testnet = inject({
49 | Msg: require('./msg').Testnet
50 | })
51 | module.exports = MsgPong
52 |
--------------------------------------------------------------------------------
/lib/msg-reject.js:
--------------------------------------------------------------------------------
1 | /**
2 | * MsgReject
3 | * ============
4 | *
5 | * Sent when a message is rejected, analous to a "404" or other HTTP error.
6 | * Conveys the reason why the message was rejected.
7 | */
8 | 'use strict'
9 | let dependencies = {
10 | Reject: require('./reject'),
11 | Msg: require('./msg')
12 | }
13 |
14 | let inject = function (deps) {
15 | let Reject = deps.Reject
16 | let Msg = deps.Msg
17 |
18 | class MsgReject extends Msg {
19 | initialize () {
20 | Msg.prototype.initialize.call(this)
21 | this.setCmd('reject')
22 | return this
23 | }
24 |
25 | fromReject (reject) {
26 | return this.setData(reject.toBuffer())
27 | }
28 |
29 | static fromReject (reject) {
30 | return new this().fromReject(reject)
31 | }
32 |
33 | asyncFromReject (reject) {
34 | return this.asyncSetData(reject.toBuffer())
35 | }
36 |
37 | static asyncFromReject (reject) {
38 | return new this().asyncFromReject(reject)
39 | }
40 |
41 | toReject () {
42 | return new Reject().fromBuffer(this.dataBuf)
43 | }
44 |
45 | isValid () {
46 | return this.getCmd() === 'reject'
47 | }
48 | }
49 |
50 | return MsgReject
51 | }
52 |
53 | inject = require('injecter')(inject, dependencies)
54 | let MsgReject = inject()
55 | MsgReject.Mainnet = inject({
56 | Msg: require('./msg').Mainnet
57 | })
58 | MsgReject.Testnet = inject({
59 | Msg: require('./msg').Testnet
60 | })
61 | module.exports = MsgReject
62 |
--------------------------------------------------------------------------------
/lib/msg-send-headers.js:
--------------------------------------------------------------------------------
1 | /**
2 | * MsgSendHeaders
3 | * ==============
4 | *
5 | * Tell peer to send block announcements using a "headers" message rather than
6 | * an "inv" message. This message has no data.
7 | */
8 | 'use strict'
9 | let dependencies = {
10 | Msg: require('./msg')
11 | }
12 |
13 | let inject = function (deps) {
14 | let Msg = deps.Msg
15 |
16 | class MsgSendHeaders extends Msg {
17 | initialize () {
18 | Msg.prototype.initialize.call(this)
19 | this.setCmd('sendheaders')
20 | this.datasize = 0
21 | this.dataBuf = new Buffer(0)
22 | this.checksumbuf = new Buffer('5df6e0e2', 'hex')
23 | return this
24 | }
25 |
26 | isValid () {
27 | return this.getCmd() === 'sendheaders' && this.dataBuf.length === 0
28 | }
29 | }
30 |
31 | return MsgSendHeaders
32 | }
33 |
34 | inject = require('injecter')(inject, dependencies)
35 | let MsgSendHeaders = inject()
36 | MsgSendHeaders.Mainnet = inject({
37 | MsgInv: require('./msg-inv').Mainnet
38 | })
39 | MsgSendHeaders.Testnet = inject({
40 | MsgInv: require('./msg-inv').Testnet
41 | })
42 | module.exports = MsgSendHeaders
43 |
--------------------------------------------------------------------------------
/lib/msg-tx.js:
--------------------------------------------------------------------------------
1 | /**
2 | * MsgTx
3 | * =====
4 | *
5 | * Sends one tx.
6 | */
7 | 'use strict'
8 | let dependencies = {
9 | Tx: require('./tx'),
10 | Msg: require('./msg')
11 | }
12 |
13 | let inject = function (deps) {
14 | let Tx = deps.Tx
15 | let Msg = deps.Msg
16 |
17 | class MsgTx extends Msg {
18 | initialize () {
19 | Msg.prototype.initialize.call(this)
20 | this.setCmd('tx')
21 | return this
22 | }
23 |
24 | fromTx (tx) {
25 | this.setData(tx.toBuffer())
26 | return this
27 | }
28 |
29 | static fromTx (tx) {
30 | return new this().fromTx(tx)
31 | }
32 |
33 | asyncFromTx (tx) {
34 | return this.asyncSetData(tx.toBuffer())
35 | }
36 |
37 | static asyncFromTx (tx) {
38 | return new this().asyncFromTx(tx)
39 | }
40 |
41 | toTx () {
42 | return new Tx().fromBuffer(this.dataBuf)
43 | }
44 |
45 | isValid () {
46 | return this.getCmd() === 'tx'
47 | }
48 | }
49 |
50 | return MsgTx
51 | }
52 |
53 | inject = require('injecter')(inject, dependencies)
54 | let MsgTx = inject()
55 | MsgTx.Mainnet = inject({
56 | Msg: require('./msg').Mainnet
57 | })
58 | MsgTx.Testnet = inject({
59 | Msg: require('./msg').Testnet
60 | })
61 | module.exports = MsgTx
62 |
--------------------------------------------------------------------------------
/lib/msg-ver-ack.js:
--------------------------------------------------------------------------------
1 | /**
2 | * MsgVerAck
3 | * =========
4 | *
5 | * Acknowledge a version message.
6 | */
7 | 'use strict'
8 | let dependencies = {
9 | Msg: require('./msg-inv')
10 | }
11 |
12 | let inject = function (deps) {
13 | let Msg = deps.Msg
14 |
15 | class MsgVerAck extends Msg {
16 | initialize () {
17 | Msg.prototype.initialize.call(this)
18 | this.setCmd('verack')
19 | this.datasize = 0
20 | this.dataBuf = new Buffer(0)
21 | this.checksumbuf = new Buffer('5df6e0e2', 'hex')
22 | return this
23 | }
24 |
25 | isValid () {
26 | return this.getCmd() === 'verack' && this.dataBuf.length === 0
27 | }
28 | }
29 |
30 | return MsgVerAck
31 | }
32 |
33 | inject = require('injecter')(inject, dependencies)
34 | let MsgVerAck = inject()
35 | MsgVerAck.Mainnet = inject({
36 | MsgInv: require('./msg-inv').Mainnet
37 | })
38 | MsgVerAck.Testnet = inject({
39 | MsgInv: require('./msg-inv').Testnet
40 | })
41 | module.exports = MsgVerAck
42 |
--------------------------------------------------------------------------------
/lib/msg-version.js:
--------------------------------------------------------------------------------
1 | /**
2 | * MsgVersion
3 | * ==========
4 | *
5 | * Sends version information about what p2p features this node or another
6 | * accepts. Confusingly, this "version" is not a number, but a data structure
7 | * used to communicate version information.
8 | */
9 | 'use strict'
10 | let dependencies = {
11 | Version: require('./version'),
12 | Msg: require('./msg')
13 | }
14 |
15 | let inject = function (deps) {
16 | let Version = deps.Version
17 | let Msg = deps.Msg
18 |
19 | class MsgVersion extends Msg {
20 | initialize () {
21 | Msg.prototype.initialize.call(this)
22 | this.setCmd('version')
23 | return this
24 | }
25 |
26 | fromVersion (version) {
27 | this.setData(version.toBuffer())
28 | return this
29 | }
30 |
31 | static fromVersion (version) {
32 | return new this().fromVersion(version)
33 | }
34 |
35 | asyncFromVersion (version) {
36 | return this.asyncSetData(version.toBuffer())
37 | }
38 |
39 | static asyncFromVersion (version) {
40 | return new this().asyncFromVersion(version)
41 | }
42 |
43 | toVersion () {
44 | return new Version().fromBuffer(this.dataBuf)
45 | }
46 |
47 | isValid () {
48 | // TODO: More validation
49 | return this.getCmd() === 'version'
50 | }
51 | }
52 |
53 | return MsgVersion
54 | }
55 |
56 | inject = require('injecter')(inject, dependencies)
57 | let MsgVersion = inject()
58 | MsgVersion.Mainnet = inject({
59 | Version: require('./version').Mainnet,
60 | Msg: require('./msg').Mainnet
61 | })
62 | MsgVersion.Testnet = inject({
63 | Version: require('./version').Testnet,
64 | Msg: require('./msg').Testnet
65 | })
66 | module.exports = MsgVersion
67 |
--------------------------------------------------------------------------------
/lib/point.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Point (on secp256k1)
3 | * ====================
4 | *
5 | * A point is a point on the secp256k1 curve which is the elliptic curve used
6 | * by bitcoin. This code is a wrapper for Fedor Indutny's Point class from his
7 | * elliptic library. This code adds a few minor conveniences, but is mostly the
8 | * same. Since Fedor's code returns points and big numbers that are instances
9 | * of his point and big number classes, we have to wrap all the methods such as
10 | * getX() to return the Yours Bitcoin point and big number types.
11 | */
12 | 'use strict'
13 | let dependencies = {
14 | Bn: require('./bn'),
15 | elliptic: require('elliptic')
16 | }
17 |
18 | let inject = function (deps) {
19 | let Bn = deps.Bn
20 | let elliptic = deps.elliptic
21 |
22 | let ec = elliptic.curves.secp256k1
23 | let _point = ec.curve.point()
24 | let _Point = _point.constructor
25 |
26 | class Point extends _Point {
27 | constructor (x, y, isRed) {
28 | super(ec.curve, x, y, isRed)
29 | }
30 |
31 | static fromX (isOdd, x) {
32 | let _point = ec.curve.pointFromX(x, isOdd)
33 | let point = Object.create(Point.prototype)
34 | return point.copyFrom(_point)
35 | }
36 |
37 | copyFrom (point) {
38 | if (!(point instanceof _Point)) {
39 | throw new Error('point should be an external point')
40 | }
41 | Object.keys(point).forEach(function (key) {
42 | this[key] = point[key]
43 | }.bind(this))
44 | return this
45 | }
46 |
47 | add (p) {
48 | p = _Point.prototype.add.call(this, p)
49 | let point = Object.create(Point.prototype)
50 | return point.copyFrom(p)
51 | }
52 |
53 | mul (bn) {
54 | let p = _Point.prototype.mul.call(this, bn)
55 | let point = Object.create(Point.prototype)
56 | return point.copyFrom(p)
57 | }
58 |
59 | mulAdd (bn1, point, bn2) {
60 | let p = _Point.prototype.mulAdd.call(this, bn1, point, bn2)
61 | point = Object.create(Point.prototype)
62 | return point.copyFrom(p)
63 | }
64 |
65 | getX () {
66 | let _x = _Point.prototype.getX.call(this)
67 | let x = Object.create(Bn.prototype)
68 | _x.copy(x)
69 | return x
70 | }
71 |
72 | getY () {
73 | let _y = _Point.prototype.getY.call(this)
74 | let y = Object.create(Bn.prototype)
75 | _y.copy(y)
76 | return y
77 | }
78 |
79 | fromX (isOdd, x) {
80 | let point = Point.fromX(isOdd, x)
81 | return this.copyFrom(point)
82 | }
83 |
84 | toJSON () {
85 | return {
86 | x: this.getX().toString(),
87 | y: this.getY().toString()
88 | }
89 | }
90 |
91 | fromJSON (json) {
92 | let x = new Bn().fromString(json.x)
93 | let y = new Bn().fromString(json.y)
94 | let point = new Point(x, y)
95 | return this.copyFrom(point)
96 | }
97 |
98 | toString () {
99 | return JSON.stringify(this.toJSON())
100 | }
101 |
102 | fromString (str) {
103 | let json = JSON.parse(str)
104 | let p = new Point().fromJSON(json)
105 | return this.copyFrom(p)
106 | }
107 |
108 | static getG () {
109 | let _g = ec.curve.g
110 | let g = Object.create(Point.prototype)
111 | return g.copyFrom(_g)
112 | }
113 |
114 | static getN () {
115 | return new Bn(ec.curve.n.toArray())
116 | }
117 |
118 | // https://www.iacr.org/archive/pkc2003/25670211/25670211.pdf
119 | validate () {
120 | let p2 = Point.fromX(this.getY().isOdd(), this.getX())
121 | if (!(p2.getY().cmp(this.getY()) === 0)) {
122 | throw new Error('Invalid y value of public key')
123 | }
124 | if (!(this.getX().gt(-1) && this.getX().lt(Point.getN())) ||
125 | !(this.getY().gt(-1) && this.getY().lt(Point.getN()))) {
126 | throw new Error('Point does not lie on the curve')
127 | }
128 | if (!(this.mul(Point.getN()).isInfinity())) {
129 | throw new Error('Point times N must be infinity')
130 | }
131 | return this
132 | }
133 | }
134 |
135 | return Point
136 | }
137 |
138 | inject = require('injecter')(inject, dependencies)
139 | let Point = inject()
140 | module.exports = Point
141 |
--------------------------------------------------------------------------------
/lib/priv-key.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Private Key
3 | * ===========
4 | *
5 | * A private key is used for signIng transactions (or messages). The primary
6 | * way to use this is new PrivKey().fromRandom(), or new PrivKey().fromBuffer(buf).
7 | */
8 | 'use strict'
9 | let dependencies = {
10 | Bn: require('./bn'),
11 | Point: require('./point'),
12 | Constants: require('./constants').Default.PrivKey,
13 | Base58Check: require('./base-58-check'),
14 | Random: require('./random'),
15 | Struct: require('./struct')
16 | }
17 |
18 | let inject = function (deps) {
19 | let Bn = deps.Bn
20 | let Point = deps.Point
21 | let Constants = deps.Constants
22 | let Base58Check = deps.Base58Check
23 | let Random = deps.Random
24 | let Struct = deps.Struct
25 |
26 | class PrivKey extends Struct {
27 | constructor (bn, compressed) {
28 | super({bn, compressed})
29 | }
30 |
31 | fromJSON (json) {
32 | this.fromHex(json)
33 | return this
34 | }
35 |
36 | toJSON () {
37 | return this.toHex()
38 | }
39 |
40 | fromRandom () {
41 | let privBuf, bn, condition
42 |
43 | do {
44 | privBuf = Random.getRandomBuffer(32)
45 | bn = new Bn().fromBuffer(privBuf)
46 | condition = bn.lt(Point.getN())
47 | } while (!condition)
48 |
49 | this.fromObject({
50 | bn: bn,
51 | compressed: true
52 | })
53 | return this
54 | }
55 |
56 | static fromRandom () {
57 | return new this().fromRandom()
58 | }
59 |
60 | toBuffer () {
61 | let compressed = this.compressed
62 |
63 | if (compressed === undefined) {
64 | compressed = true
65 | }
66 |
67 | let privBuf = this.bn.toBuffer({size: 32})
68 | let buf
69 | if (compressed) {
70 | buf = Buffer.concat([new Buffer([Constants.versionByteNum]), privBuf, new Buffer([0x01])])
71 | } else {
72 | buf = Buffer.concat([new Buffer([Constants.versionByteNum]), privBuf])
73 | }
74 |
75 | return buf
76 | }
77 |
78 | fromBuffer (buf) {
79 | if (buf.length === 1 + 32 + 1 && buf[1 + 32 + 1 - 1] === 1) {
80 | this.compressed = true
81 | } else if (buf.length === 1 + 32) {
82 | this.compressed = false
83 | } else {
84 | throw new Error('LEngth of privKey buffer must be 33 (uncompressed pubKey) or 34 (compressed pubKey)')
85 | }
86 |
87 | if (buf[0] !== Constants.versionByteNum) {
88 | throw new Error('Invalid versionByteNum byte')
89 | }
90 |
91 | return this.fromBn(new Bn().fromBuffer(buf.slice(1, 1 + 32)))
92 | }
93 |
94 | toBn () {
95 | return this.bn
96 | }
97 |
98 | fromBn (bn) {
99 | this.bn = bn
100 | return this
101 | }
102 |
103 | static fromBn (bn) {
104 | return new this().fromBn(bn)
105 | }
106 |
107 | validate () {
108 | if (!this.bn.lt(Point.getN())) {
109 | throw new Error('Number must be less than N')
110 | }
111 | if (typeof this.compressed !== 'boolean') {
112 | throw new Error('Must specify whether the corresponding public key is compressed or not (true or false)')
113 | }
114 | return this
115 | }
116 |
117 | /**
118 | * Output the private key a Wallet Import Format (Wif) string.
119 | */
120 | toWif () {
121 | return Base58Check.encode(this.toBuffer())
122 | }
123 |
124 | /**
125 | * Input the private key from a Wallet Import Format (Wif) string.
126 | */
127 | fromWif (str) {
128 | return this.fromBuffer(Base58Check.decode(str))
129 | }
130 |
131 | static fromWif (str) {
132 | return new this().fromWif(str)
133 | }
134 |
135 | toString () {
136 | return this.toWif()
137 | }
138 |
139 | fromString (str) {
140 | return this.fromWif(str)
141 | }
142 | }
143 |
144 | return PrivKey
145 | }
146 |
147 | inject = require('injecter')(inject, dependencies)
148 | let PrivKey = inject()
149 | PrivKey.Mainnet = inject({
150 | Constants: require('./constants').Mainnet.PrivKey
151 | })
152 | PrivKey.Testnet = inject({
153 | Constants: require('./constants').Testnet.PrivKey
154 | })
155 | module.exports = PrivKey
156 |
--------------------------------------------------------------------------------
/lib/random.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Random Number Generator
3 | * =======================
4 | *
5 | * Random numbers are important in bitcoin primarily for generating private
6 | * keys. It is also important for creating signatures if you are using a random
7 | * value of k, but Yours Bitcoin defaults to using deterministic k. That means
8 | * computing a random private key, or a random seed for use in Bip39 or Bip32,
9 | * is the primary use of the random number generator. Note that the simplicity
10 | * of this class is extremely carefully considered. It is easy to audit that
11 | * this code runs node's randomBytes function. It is also easy to audit that
12 | * the randomBytes method is correctly interpreted as
13 | * window.crypto.getRandomValues when this code is browserified by browserify,
14 | * and thus also works correctly in the browser. We deliberately do not do
15 | * anything else to this random number in order to minimize possible errors in
16 | * this absolutely critical code.
17 | */
18 | 'use strict'
19 | let dependencies = {
20 | randomBytes: require('randombytes')
21 | }
22 |
23 | let inject = function (deps) {
24 | let randomBytes = deps.randomBytes
25 |
26 | let Random = {}
27 |
28 | Random.getRandomBuffer = function (size) {
29 | return randomBytes(size)
30 | }
31 |
32 | return Random
33 | }
34 |
35 | inject = require('injecter')(inject, dependencies)
36 | let Random = inject()
37 | module.exports = Random
38 |
--------------------------------------------------------------------------------
/lib/reject.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Reject
3 | * =========
4 | *
5 | * The data structure used inside the "reject" p2p message. Contains a reason
6 | * why a particular message was rejected. Useful for debugging.
7 | */
8 | 'use strict'
9 | let dependencies = {
10 | Bw: require('./bw'),
11 | Struct: require('./struct'),
12 | VarInt: require('./var-int')
13 | }
14 |
15 | let inject = function (deps) {
16 | let Bw = deps.Bw
17 | let Struct = deps.Struct
18 | let VarInt = deps.VarInt
19 |
20 | class Reject extends Struct {
21 | constructor (typeVi, typeStr, codeNum, reasonVi, reasonStr, extraBuf) {
22 | super({typeVi, typeStr, codeNum, reasonVi, reasonStr, extraBuf})
23 | }
24 |
25 | toBw (bw) {
26 | if (!bw) {
27 | bw = new Bw()
28 | }
29 | bw.write(this.typeVi.buf)
30 | bw.write(new Buffer(this.typeStr))
31 | bw.writeUInt8(this.codeNum)
32 | bw.write(this.reasonVi.buf)
33 | bw.write(new Buffer(this.reasonStr))
34 | bw.write(this.extraBuf)
35 | return bw
36 | }
37 |
38 | fromBr (br) {
39 | this.typeVi = new VarInt(br.readVarIntBuf())
40 | this.typeStr = br.read(this.typeVi.toNumber()).toString()
41 | this.codeNum = br.readUInt8()
42 | this.reasonVi = new VarInt(br.readVarIntBuf())
43 | this.reasonStr = br.read(this.reasonVi.toNumber()).toString()
44 | this.extraBuf = br.read()
45 | return this
46 | }
47 | }
48 |
49 | return Reject
50 | }
51 |
52 | inject = require('injecter')(inject, dependencies)
53 | let Reject = inject()
54 | module.exports = Reject
55 |
--------------------------------------------------------------------------------
/lib/tx-out-map.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Transaction Output Map
3 | * ======================
4 | *
5 | * A map from a transaction hash and output number to that particular output.
6 | * Note that the map is from the transaction *hash*, which is the value that
7 | * occurs in the blockchain, not the id, which is the reverse of the hash.
8 | */
9 | 'use strict'
10 | let dependencies = {
11 | Struct: require('./struct'),
12 | TxOut: require('./tx-out')
13 | }
14 |
15 | let inject = function (deps) {
16 | let Struct = deps.Struct
17 | let TxOut = deps.TxOut
18 |
19 | class TxOutMap extends Struct {
20 | constructor (map = new Map()) {
21 | super({map})
22 | }
23 |
24 | toJSON () {
25 | let json = {}
26 | this.map.forEach((txOut, label) => {
27 | json[label] = txOut.toHex()
28 | })
29 | return json
30 | }
31 |
32 | fromJSON (json) {
33 | Object.keys(json).forEach((label) => {
34 | this.map.set(label, TxOut.fromHex(json[label]))
35 | })
36 | return this
37 | }
38 |
39 | add (txHashBuf, txOutNum, txOut) {
40 | let label = txHashBuf.toString('hex') + ':' + txOutNum
41 | this.map.set(label, txOut)
42 | return this
43 | }
44 |
45 | get (txHashBuf, txOutNum) {
46 | let label = txHashBuf.toString('hex') + ':' + txOutNum
47 | return this.map.get(label)
48 | }
49 |
50 | addTx (tx) {
51 | let txhashhex = tx.hash().toString('hex')
52 | tx.txOuts.forEach((txOut, index) => {
53 | let label = txhashhex + ':' + index
54 | this.map.set(label, txOut)
55 | })
56 | return this
57 | }
58 | }
59 |
60 | return TxOutMap
61 | }
62 |
63 | inject = require('injecter')(inject, dependencies)
64 | let TxOutMap = inject()
65 | module.exports = TxOutMap
66 |
--------------------------------------------------------------------------------
/lib/tx-out.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Transaction Output
3 | * ==================
4 | *
5 | * An output to a transaction. The way you normally want to make one is with
6 | * new TxOut(valueBn, script) (i.e., just as with TxIn, you can leave out the
7 | * scriptVi, since it can be computed automatically.
8 | */
9 | 'use strict'
10 | let dependencies = {
11 | Bn: require('./bn'),
12 | Bw: require('./bw'),
13 | Script: require('./script'),
14 | Struct: require('./struct'),
15 | VarInt: require('./var-int')
16 | }
17 |
18 | let inject = function (deps) {
19 | let Bn = deps.Bn
20 | let Bw = deps.Bw
21 | let Script = deps.Script
22 | let Struct = deps.Struct
23 | let VarInt = deps.VarInt
24 |
25 | class TxOut extends Struct {
26 | constructor (valueBn, scriptVi, script) {
27 | super({valueBn, scriptVi, script})
28 | }
29 |
30 | setScript (script) {
31 | this.scriptVi = VarInt.fromNumber(script.toBuffer().length)
32 | this.script = script
33 | return this
34 | }
35 |
36 | fromProperties (valueBn, script) {
37 | this.fromObject({valueBn})
38 | this.setScript(script)
39 | return this
40 | }
41 |
42 | static fromProperties (valueBn, script) {
43 | return new this().fromProperties(valueBn, script)
44 | }
45 |
46 | fromJSON (json) {
47 | this.fromObject({
48 | valueBn: new Bn().fromJSON(json.valueBn),
49 | scriptVi: new VarInt().fromJSON(json.scriptVi),
50 | script: new Script().fromJSON(json.script)
51 | })
52 | return this
53 | }
54 |
55 | toJSON () {
56 | return {
57 | valueBn: this.valueBn.toJSON(),
58 | scriptVi: this.scriptVi.toJSON(),
59 | script: this.script.toJSON()
60 | }
61 | }
62 |
63 | fromBr (br) {
64 | this.valueBn = br.readUInt64LEBn()
65 | this.scriptVi = VarInt.fromNumber(br.readVarIntNum())
66 | this.script = new Script().fromBuffer(br.read(this.scriptVi.toNumber()))
67 | return this
68 | }
69 |
70 | toBw (bw) {
71 | if (!bw) {
72 | bw = new Bw()
73 | }
74 | bw.writeUInt64LEBn(this.valueBn)
75 | bw.write(this.scriptVi.buf)
76 | bw.write(this.script.toBuffer())
77 | return bw
78 | }
79 | }
80 |
81 | return TxOut
82 | }
83 |
84 | inject = require('injecter')(inject, dependencies)
85 | let TxOut = inject()
86 | module.exports = TxOut
87 |
--------------------------------------------------------------------------------
/lib/var-int.js:
--------------------------------------------------------------------------------
1 | /**
2 | * VarInt (a.k.a. Compact Size)
3 | * ============================
4 | *
5 | * A varInt is a varible sized integer, and it is a format that is unique to
6 | * bitcoin, and used throughout bitcoin to represent the length of binary data
7 | * in a compact format that can take up as little as 1 byte or as much as 9
8 | * bytes.
9 | */
10 | 'use strict'
11 | let dependencies = {
12 | Br: require('./br'),
13 | Bw: require('./bw'),
14 | Struct: require('./struct')
15 | }
16 |
17 | let inject = function (deps) {
18 | let Br = deps.Br
19 | let Bw = deps.Bw
20 | let Struct = deps.Struct
21 |
22 | class VarInt extends Struct {
23 | constructor (buf) {
24 | super({buf})
25 | }
26 |
27 | fromJSON (json) {
28 | this.fromObject({
29 | buf: new Buffer(json, 'hex')
30 | })
31 | return this
32 | }
33 |
34 | toJSON () {
35 | return this.buf.toString('hex')
36 | }
37 |
38 | fromBuffer (buf) {
39 | this.buf = buf
40 | return this
41 | }
42 |
43 | fromBr (br) {
44 | this.buf = br.readVarIntBuf()
45 | return this
46 | }
47 |
48 | fromBn (bn) {
49 | this.buf = new Bw().writeVarIntBn(bn).toBuffer()
50 | return this
51 | }
52 |
53 | static fromBn (bn) {
54 | return new this().fromBn(bn)
55 | }
56 |
57 | fromNumber (num) {
58 | this.buf = new Bw().writeVarIntNum(num).toBuffer()
59 | return this
60 | }
61 |
62 | static fromNumber (num) {
63 | return new this().fromNumber(num)
64 | }
65 |
66 | toBuffer () {
67 | return this.buf
68 | }
69 |
70 | toBn () {
71 | return new Br(this.buf).readVarIntBn()
72 | }
73 |
74 | toNumber () {
75 | return new Br(this.buf).readVarIntNum()
76 | }
77 | }
78 |
79 | return VarInt
80 | }
81 |
82 | inject = require('injecter')(inject, dependencies)
83 | let VarInt = inject()
84 | module.exports = VarInt
85 |
--------------------------------------------------------------------------------
/lib/version.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Version
3 | * =======
4 | *
5 | * This data structure is used to specify details about what version of the
6 | * p2p network is supported by this or other nodes.
7 | */
8 | 'use strict'
9 | let dependencies = {
10 | Bw: require('./bw'),
11 | Struct: require('./struct'),
12 | VarInt: require('./var-int')
13 | }
14 |
15 | let inject = function (deps) {
16 | let Bw = deps.Bw
17 | let Struct = deps.Struct
18 | let VarInt = deps.VarInt
19 |
20 | class Version extends Struct {
21 | constructor (versionBytesNum, servicesBuf, timeBn, addrRecvServicesBuf, addrRecvIpAddrBuf, addrRecvPort, addrTransServicesBuf, addrTransIpAddrBuf, addrTransPortBuf, nonceBuf, userAgentVi, userAgentBuf, startHeightNum, relay) {
22 | super({versionBytesNum, servicesBuf, timeBn, addrRecvServicesBuf, addrRecvIpAddrBuf, addrRecvPort, addrTransServicesBuf, addrTransIpAddrBuf, addrTransPortBuf, nonceBuf, userAgentVi, userAgentBuf, startHeightNum, relay})
23 | }
24 |
25 | toBw (bw) {
26 | if (!bw) {
27 | bw = new Bw()
28 | }
29 | bw.writeUInt32LE(this.versionBytesNum)
30 | bw.write(this.servicesBuf)
31 | bw.writeUInt64LEBn(this.timeBn)
32 | bw.write(this.addrRecvServicesBuf)
33 | bw.write(this.addrRecvIpAddrBuf)
34 | bw.writeUInt16BE(this.addrRecvPort) // note BE
35 | bw.write(this.addrTransServicesBuf)
36 | bw.write(this.addrTransIpAddrBuf)
37 | bw.writeUInt16BE(this.addrTransPort) // note BE
38 | bw.write(this.nonceBuf)
39 | bw.write(this.userAgentVi.buf)
40 | bw.write(this.userAgentBuf)
41 | bw.writeUInt32LE(this.startHeightNum)
42 | bw.writeUInt8(Number(this.relay))
43 | return bw
44 | }
45 |
46 | fromBr (br) {
47 | this.versionBytesNum = br.readUInt32LE()
48 | this.servicesBuf = br.read(8)
49 | this.timeBn = br.readUInt64LEBn()
50 | this.addrRecvServicesBuf = br.read(8)
51 | this.addrRecvIpAddrBuf = br.read(16)
52 | this.addrRecvPort = br.readUInt16BE() // note BE
53 | this.addrTransServicesBuf = br.read(8)
54 | this.addrTransIpAddrBuf = br.read(16)
55 | this.addrTransPort = br.readUInt16BE() // note BE
56 | this.nonceBuf = br.read(8)
57 | this.userAgentVi = new VarInt(br.readVarIntBuf())
58 | this.userAgentBuf = br.read(this.userAgentVi.toNumber())
59 | this.startHeightNum = br.readUInt32LE()
60 | this.relay = Boolean(br.readUInt8())
61 | return this
62 | }
63 | }
64 |
65 | return Version
66 | }
67 |
68 | inject = require('injecter')(inject, dependencies)
69 | let Version = inject()
70 | module.exports = Version
71 |
--------------------------------------------------------------------------------
/lib/worker-browser.js:
--------------------------------------------------------------------------------
1 | /* global importScripts,YoursBitcoin,postMessage */
2 | /**
3 | * Worker
4 | * ======
5 | *
6 | * This class is for running CPU-heavy, blocking operations. It either runs in
7 | * a separate process (in node), or in a web worker thread (in a browser). It
8 | * receives messages from outside, performs the computation, and then sends
9 | * back the result. You probably don't want to use this file directly, but
10 | * rather Work, which will automatically spawn workers if necessary and send
11 | * commands to them. Note that the source code for worker-node and
12 | * worker-browser are almost equivalent, except for code that manages the
13 | * differences at the bottom. This is done deliberately, so that the browser
14 | * version can be minimized properly.
15 | */
16 | 'use strict'
17 |
18 | // The Yours Bitcoin "classes" that the worker can access. Objects sent from the
19 | // main process/thread must be one of these types. They are defined below in a
20 | // different way for node and the browser.
21 | let classes
22 |
23 | // The function to send data back to the main process/thread. This is different
24 | // for node and browsers and thus is defined below.
25 | let send
26 |
27 | // len is the length of the data being sent to the worker - which may come in
28 | // pieces. bw is a BufferWriter used to assemble the pieces, if necessary.
29 | let len
30 | let bw
31 |
32 | /**
33 | * The generic "receive data" method that works both in node and the browser.
34 | * It reconstitutes the data into an object of class classname, and then runs
35 | * the method methodname on it with arguments args.
36 | */
37 | function receive (buf) {
38 | let WorkersCmd = classes['WorkersCmd']
39 | let WorkersResult = classes['WorkersResult']
40 | let Bw = classes['Bw']
41 | let remainderbuf
42 |
43 | // buffers sent to us are prefixed with the length. If the buffer has been
44 | // broken up into pieces, we need to assemble them.
45 | if (!bw) {
46 | if (buf.length < 4) {
47 | let workersResult = new WorkersResult().fromError(new Error('buf must be prefixed with length'))
48 | send(workersResult.toFastBuffer())
49 | return
50 | }
51 | len = buf.readUInt32BE(0)
52 | if (len > buf.length - 4) {
53 | bw = new Bw()
54 | bw.write(buf.slice(4))
55 | // need to wait for the rest of the message
56 | return
57 | } else if (len < buf.length - 4) {
58 | // sent more than one message
59 | remainderbuf = buf.slice(len + 4)
60 | buf = buf.slice(0, len + 4)
61 | }
62 |
63 | // else, the entire buf was sent in one message, can continue
64 | buf = buf.slice(4)
65 | } else {
66 | // getting a new piece of the message
67 | bw.write(buf)
68 | if (bw.getLength() < len) {
69 | // need to wait for more data
70 | return
71 | }
72 | // got all data!
73 | buf = bw.toBuffer()
74 | bw = undefined
75 | }
76 |
77 | let obj, result, id
78 | try {
79 | let workersCmd = new WorkersCmd().fromFastBuffer(buf, classes)
80 | id = workersCmd.id
81 | if (workersCmd.isobj) {
82 | obj = new classes[workersCmd.classname]().fromFastBuffer(workersCmd.objbuf)
83 | } else {
84 | obj = classes[workersCmd.classname]
85 | }
86 | result = obj[workersCmd.methodname].apply(obj, workersCmd.args)
87 | } catch (error) {
88 | if (!id) {
89 | id = 0 // must be uint
90 | }
91 | let workersResult = new WorkersResult().fromError(error, id)
92 | send(workersResult.toFastBuffer())
93 | return
94 | }
95 | let workersResult = new WorkersResult().fromResult(result, id)
96 | send(workersResult.toFastBuffer())
97 |
98 | if (remainderbuf) {
99 | receive(remainderbuf)
100 | }
101 | }
102 |
103 | // Load the main Yours Bitcoin library so we have access to classes like Msg; it
104 | // is assumed the full library is available. It is usually called
105 | // yours-bitcoin.js. It sets a global object called YoursBitcoin.
106 | importScripts(process.env.YOURS_BITCOIN_JS_BASE_URL + process.env.YOURS_BITCOIN_JS_BUNDLE_FILE)
107 | classes = YoursBitcoin
108 | // Web workers use the global functions onmessage to receive, and postMessage
109 | // to send.
110 | onmessage = function (event) { // eslint-disable-line
111 | let buf = new YoursBitcoin.deps.Buffer(event.data)
112 | return receive(buf)
113 | }
114 | send = postMessage
115 |
--------------------------------------------------------------------------------
/lib/worker-node.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Worker
3 | * ======
4 | *
5 | * This class is for running CPU-heavy, blocking operations. It either runs in
6 | * a separate process (in node), or in a web worker thread (in a browser). It
7 | * receives messages from outside, performs the computation, and then sends
8 | * back the result. You probably don't want to use this file directly, but
9 | * rather Work, which will automatically spawn workers if necessary and send
10 | * commands to them. Note that the source code for worker-node and
11 | * worker-browser are almost equivalent, except for code that manages the
12 | * differences at the bottom. This is done deliberately, so that the browser
13 | * version can be minimized properly.
14 | */
15 | 'use strict'
16 |
17 | // The Yours Bitcoin "classes" that the worker can access. Objects sent from the
18 | // main process/thread must be one of these types. They are defined below in a
19 | // different way for node and the browser.
20 | let classes
21 |
22 | // The function to send data back to the main process/thread. This is different
23 | // for node and browsers and thus is defined below.
24 | let send
25 |
26 | // len is the length of the data being sent to the worker - which may come in
27 | // pieces. bw is a BufferWriter used to assemble the pieces, if necessary.
28 | let len
29 | let bw
30 |
31 | /**
32 | * The generic "receive data" method that works both in node and the browser.
33 | * It reconstitutes the data into an object of class classname, and then runs
34 | * the method methodname on it with arguments args.
35 | */
36 | function receive (buf) {
37 | let WorkersCmd = classes['WorkersCmd']
38 | let WorkersResult = classes['WorkersResult']
39 | let Bw = classes['Bw']
40 | let remainderbuf
41 |
42 | // buffers sent to us are prefixed with the length. If the buffer has been
43 | // broken up into pieces, we need to assemble them.
44 | if (!bw) {
45 | if (buf.length < 4) {
46 | let workersResult = new WorkersResult().fromError(new Error('buf must be prefixed with length'))
47 | send(workersResult.toFastBuffer())
48 | return
49 | }
50 | len = buf.readUInt32BE(0)
51 | if (len > buf.length - 4) {
52 | bw = new Bw()
53 | bw.write(buf.slice(4))
54 | // need to wait for the rest of the message
55 | return
56 | } else if (len < buf.length - 4) {
57 | // sent more than one message
58 | remainderbuf = buf.slice(len + 4)
59 | buf = buf.slice(0, len + 4)
60 | }
61 |
62 | // else, the entire buf was sent in one message, can continue
63 | buf = buf.slice(4)
64 | } else {
65 | // getting a new piece of the message
66 | bw.write(buf)
67 | if (bw.getLength() < len) {
68 | // need to wait for more data
69 | return
70 | }
71 | // got all data!
72 | buf = bw.toBuffer()
73 | bw = undefined
74 | }
75 |
76 | let obj, result, id
77 | try {
78 | let workersCmd = new WorkersCmd().fromFastBuffer(buf, classes)
79 | id = workersCmd.id
80 | if (workersCmd.isobj) {
81 | obj = new classes[workersCmd.classname]().fromFastBuffer(workersCmd.objbuf)
82 | } else {
83 | obj = classes[workersCmd.classname]
84 | }
85 | result = obj[workersCmd.methodname].apply(obj, workersCmd.args)
86 | } catch (error) {
87 | if (!id) {
88 | id = 0 // must be uint
89 | }
90 | let workersResult = new WorkersResult().fromError(error, id)
91 | send(workersResult.toFastBuffer())
92 | return
93 | }
94 | let workersResult = new WorkersResult().fromResult(result, id)
95 | send(workersResult.toFastBuffer())
96 |
97 | if (remainderbuf) {
98 | receive(remainderbuf)
99 | }
100 | }
101 |
102 | // Node uses process.on and process.send to receive and send messages.
103 | classes = require('../index')
104 | process.stdin.on('data', function (buf) {
105 | return receive(buf)
106 | })
107 | send = process.stdout.write.bind(process.stdout)
108 |
--------------------------------------------------------------------------------
/lib/workers-result.js:
--------------------------------------------------------------------------------
1 | /**
2 | * WorkersResult
3 | * =============
4 | *
5 | * A response sent back from a worker to the main thread. Contains the "result"
6 | * of the computation in the form of a buffer, resbuf. If the actual result is
7 | * an object with a .toFastBuffer method, the object is converted to a buffer
8 | * using that method. Otherwise it is JSON serialized into a buffer. The result
9 | * can also be an error, in which case the isError flag is set.
10 | */
11 | 'use strict'
12 | let dependencies = {
13 | Bw: require('./bw'),
14 | Struct: require('./struct')
15 | }
16 |
17 | let inject = function (deps) {
18 | let Bw = deps.Bw
19 | let Struct = deps.Struct
20 |
21 | class WorkersResult extends Struct {
22 | constructor (resbuf, isError, id) {
23 | super({resbuf, isError, id})
24 | }
25 |
26 | fromResult (result, id) {
27 | if (result.toFastBuffer) {
28 | this.resbuf = result.toFastBuffer()
29 | } else if (Buffer.isBuffer(result)) {
30 | this.resbuf = result
31 | } else {
32 | this.resbuf = new Buffer(JSON.stringify(result))
33 | }
34 | this.isError = false
35 | this.id = id
36 | return this
37 | }
38 |
39 | static fromResult (result, id) {
40 | return new this().fromResult(result, id)
41 | }
42 |
43 | fromError (error, id) {
44 | this.resbuf = new Buffer(JSON.stringify(error.message))
45 | this.isError = true
46 | this.id = id
47 | return this
48 | }
49 |
50 | toBw (bw) {
51 | if (!bw) {
52 | bw = new Bw()
53 | }
54 | bw.writeVarIntNum(this.resbuf.length)
55 | bw.write(this.resbuf)
56 | bw.writeUInt8(Number(this.isError))
57 | bw.writeVarIntNum(this.id)
58 | return bw
59 | }
60 |
61 | fromBr (br) {
62 | let resbuflen = br.readVarIntNum()
63 | this.resbuf = br.read(resbuflen)
64 | this.isError = Boolean(br.readUInt8())
65 | this.id = br.readVarIntNum()
66 | return this
67 | }
68 | }
69 |
70 | return WorkersResult
71 | }
72 |
73 | inject = require('injecter')(inject, dependencies)
74 | let WorkersResult = inject()
75 | module.exports = WorkersResult
76 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "yours-bitcoin",
3 | "version": "0.14.14",
4 | "description": "Javascript implementation of Bitcoin.",
5 | "author": "Ryan X. Charles ",
6 | "homepage": "https://github.com/yoursnetwork/yours-bitcoin",
7 | "main": "index.js",
8 | "scripts": {
9 | "coverage": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha -- --recursive -R progress",
10 | "parallel": "./node_modules/.bin/standard && ./bin/test-parallel",
11 | "test-node": "./node_modules/.bin/standard && ./node_modules/.bin/mocha --recursive -R progress",
12 | "test-browser": "./node_modules/.bin/gulp test-karma",
13 | "test": "npm run test-node && npm run test-browser",
14 | "build": "./node_modules/.bin/gulp build"
15 | },
16 | "browserify": {
17 | "transform": [
18 | [
19 | "babelify",
20 | {
21 | "presets": [
22 | "es2015"
23 | ]
24 | }
25 | ]
26 | ]
27 | },
28 | "contributors": [
29 | {
30 | "name": "Daniel Cousens",
31 | "email": "bitcoin@dcousens.com"
32 | },
33 | {
34 | "name": "Gordon Hall",
35 | "email": "gordon@bitpay.com"
36 | },
37 | {
38 | "name": "Jeff Garzik",
39 | "email": "jgarzik@bitpay.com"
40 | },
41 | {
42 | "name": "Kyle Drake",
43 | "email": "kyle@kyledrake.net"
44 | },
45 | {
46 | "name": "Manuel Araoz",
47 | "email": "manuelaraoz@gmail.com"
48 | },
49 | {
50 | "name": "Matias Alejo Garcia",
51 | "email": "ematiu@gmail.com"
52 | },
53 | {
54 | "name": "Ryan X. Charles",
55 | "email": "ryanxcharles@gmail.com"
56 | },
57 | {
58 | "name": "Stefan Thomas",
59 | "email": "moon@justmoon.net"
60 | },
61 | {
62 | "name": "Stephen Pair",
63 | "email": "stephen@bitpay.com"
64 | },
65 | {
66 | "name": "Wei Lu",
67 | "email": "luwei.here@gmail.com"
68 | }
69 | ],
70 | "keywords": [
71 | "bitcoin",
72 | "blockchain",
73 | "bip32",
74 | "bip39",
75 | "bip68",
76 | "multisig"
77 | ],
78 | "repository": {
79 | "type": "git",
80 | "url": "https://github.com/yoursnetwork/yours-bitcoin.git"
81 | },
82 | "engines": {
83 | "node": ">=6.1.0"
84 | },
85 | "dependencies": {
86 | "aes": "0.1.0",
87 | "asink": "1.0.4",
88 | "babel-polyfill": "6.9.1",
89 | "babel-preset-es2015": "6.9.0",
90 | "babel-preset-react": "6.11.1",
91 | "babelify": "7.3.0",
92 | "bn.js": "4.11.4",
93 | "browserify": "13.0.1",
94 | "bs58": "3.0.0",
95 | "elliptic": "6.3.1",
96 | "envify": "3.4.1",
97 | "express": "4.14.0",
98 | "glob": "7.0.5",
99 | "gulp": "3.9.1",
100 | "gulp-mocha": "2.2.0",
101 | "hash.js": "1.0.3",
102 | "injecter": "1.0.2",
103 | "istanbul": "0.4.4",
104 | "karma": "1.1.0",
105 | "karma-mocha": "1.1.1",
106 | "mocha": "2.5.3",
107 | "pbkdf2-compat": "4.0.0",
108 | "randombytes": "2.0.3",
109 | "standard": "7.1.2",
110 | "uglifyify": "3.0.2"
111 | },
112 | "devDependencies": {
113 | "chai": "3.5.0",
114 | "express": "4.13.4",
115 | "istanbul": "0.4.3",
116 | "karma": "0.13.22",
117 | "karma-firefox-launcher": "1.0.0",
118 | "karma-mocha": "1.0.1",
119 | "mocha": "2.4.5",
120 | "sinon": "1.17.4",
121 | "standard": "7.0.1"
122 | },
123 | "license": "MIT"
124 | }
125 |
--------------------------------------------------------------------------------
/test/addr.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let Addr = require('../lib/addr')
4 | let should = require('chai').should()
5 |
6 | describe('Addr', function () {
7 | it('should exist', function () {
8 | should.exist(Addr)
9 | should.exist(new Addr())
10 | })
11 |
12 | describe('#toBuffer', function () {
13 | it('should convert an addr to a buffer', function () {
14 | let addr = new Addr().fromObject({
15 | time: 1000,
16 | servicesBuf: new Buffer(8).fill(0),
17 | ipAddrBuf: new Buffer(16).fill(0),
18 | port: 8333
19 | })
20 | addr.toBuffer().length.should.equal(4 + 8 + 16 + 2)
21 | })
22 | })
23 |
24 | describe('#toBuffer', function () {
25 | it('should convert an addr to a buffer', function () {
26 | let addr = new Addr().fromObject({
27 | time: 1000,
28 | servicesBuf: new Buffer(8).fill(0),
29 | ipAddrBuf: new Buffer(16).fill(0),
30 | port: 8333
31 | })
32 | let addr2 = new Addr().fromBuffer(addr.toBuffer())
33 | addr2.time.should.equal(addr.time)
34 | Buffer.compare(addr.servicesBuf, addr2.servicesBuf).should.equal(0)
35 | Buffer.compare(addr.ipAddrBuf, addr2.ipAddrBuf).should.equal(0)
36 | addr2.port.should.equal(addr.port)
37 | })
38 | })
39 |
40 | describe('@fromBuffer', function () {
41 | it('should convert from a buffer', function () {
42 | let addr = Addr.fromObject({
43 | time: 1000,
44 | servicesBuf: new Buffer(8).fill(0),
45 | ipAddrBuf: new Buffer(16).fill(0),
46 | port: 8333
47 | })
48 | let addr2 = Addr.fromBuffer(addr.toBuffer())
49 | addr2.time.should.equal(addr.time)
50 | Buffer.compare(addr.servicesBuf, addr2.servicesBuf).should.equal(0)
51 | Buffer.compare(addr.ipAddrBuf, addr2.ipAddrBuf).should.equal(0)
52 | addr2.port.should.equal(addr.port)
53 | })
54 | })
55 | })
56 |
--------------------------------------------------------------------------------
/test/aes.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let should = require('chai').should()
4 | let Hash = require('../lib/hash')
5 | let Aes = require('../lib/aes')
6 | let vectors = require('./vectors/aes')
7 |
8 | describe('Aes', function () {
9 | let m128 = Hash.sha256(new Buffer('test1')).slice(0, 128 / 8)
10 |
11 | let k128 = Hash.sha256(new Buffer('test2')).slice(0, 128 / 8)
12 | let k192 = Hash.sha256(new Buffer('test2')).slice(0, 192 / 8)
13 | let k256 = Hash.sha256(new Buffer('test2')).slice(0, 256 / 8)
14 |
15 | let e128 = new Buffer('3477e13884125038f4dc24e9d2cfbbc7', 'hex')
16 | let e192 = new Buffer('b670954c0e2da1aaa5f9063de04eb961', 'hex')
17 | let e256 = new Buffer('dd2ce24581183a4a7c0b1068f8bc79f0', 'hex')
18 |
19 | should.exist(Aes)
20 |
21 | describe('@encrypt', function () {
22 | it('should encrypt with a 128 bit key', function () {
23 | let encBuf = Aes.encrypt(m128, k128)
24 | encBuf.toString('hex').should.equal(e128.toString('hex'))
25 | })
26 |
27 | it('should encrypt with a 192 bit key', function () {
28 | let encBuf = Aes.encrypt(m128, k192)
29 | encBuf.toString('hex').should.equal(e192.toString('hex'))
30 | })
31 |
32 | it('should encrypt with a 256 bit key', function () {
33 | let encBuf = Aes.encrypt(m128, k256)
34 | encBuf.toString('hex').should.equal(e256.toString('hex'))
35 | })
36 | })
37 |
38 | describe('@decrypt', function () {
39 | it('should encrypt/decrypt with a 128 bit key', function () {
40 | let encBuf = Aes.encrypt(m128, k128)
41 | let m = Aes.decrypt(encBuf, k128)
42 | m.toString('hex').should.equal(m128.toString('hex'))
43 | })
44 |
45 | it('should encrypt/decrypt with a 192 bit key', function () {
46 | let encBuf = Aes.encrypt(m128, k192)
47 | let m = Aes.decrypt(encBuf, k192)
48 | m.toString('hex').should.equal(m128.toString('hex'))
49 | })
50 |
51 | it('should encrypt/decrypt with a 256 bit key', function () {
52 | let encBuf = Aes.encrypt(m128, k256)
53 | let m = Aes.decrypt(encBuf, k256)
54 | m.toString('hex').should.equal(m128.toString('hex'))
55 | })
56 | })
57 |
58 | describe('@buf2Words', function () {
59 | it('should convert this 4 length buffer into an array', function () {
60 | let buf = new Buffer([0, 0, 0, 0])
61 | let words = Aes.buf2Words(buf)
62 | words.length.should.equal(1)
63 | })
64 |
65 | it('should throw an error on this 5 length buffer', function () {
66 | let buf = new Buffer([0, 0, 0, 0, 0])
67 | ;(function () {
68 | Aes.buf2Words(buf)
69 | }).should.throw()
70 | })
71 | })
72 |
73 | describe('@words2Buf', function () {
74 | it('should convert this array into a buffer', function () {
75 | let a = [100, 0]
76 | let buf = Aes.words2Buf(a)
77 | buf.length.should.equal(8)
78 | })
79 | })
80 |
81 | describe('vectors', function () {
82 | vectors.forEach(function (vector, i) {
83 | it('should pass sjcl test vector ' + i, function () {
84 | let keyBuf = new Buffer(vector.key, 'hex')
85 | let ptbuf = new Buffer(vector.pt, 'hex')
86 | let ctBuf = new Buffer(vector.ct, 'hex')
87 |
88 | Aes.encrypt(ptbuf, keyBuf).toString('hex').should.equal(ctBuf.toString('hex'))
89 | Aes.decrypt(ctBuf, keyBuf).toString('hex').should.equal(ptbuf.toString('hex'))
90 | })
91 | })
92 | })
93 | })
94 |
--------------------------------------------------------------------------------
/test/aescbc.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let should = require('chai').should()
4 | let Aescbc = require('../lib/aescbc')
5 | let vectors = require('./vectors/aescbc')
6 |
7 | describe('Aescbc', function () {
8 | should.exist(Aescbc)
9 |
10 | describe('@encrypt', function () {
11 | it('should return encrypt one block', function () {
12 | let cipherKeyBuf = new Buffer(256 / 8)
13 | cipherKeyBuf.fill(0x10)
14 | let ivBuf = new Buffer(128 / 8)
15 | ivBuf.fill(0)
16 | let messageBuf = new Buffer(128 / 8 - 1)
17 | messageBuf.fill(0)
18 | let encBuf = Aescbc.encrypt(messageBuf, cipherKeyBuf, ivBuf)
19 | encBuf.length.should.equal(128 / 8 + 128 / 8)
20 | })
21 |
22 | it('should return encrypt two blocks', function () {
23 | let cipherKeyBuf = new Buffer(256 / 8)
24 | cipherKeyBuf.fill(0x10)
25 | let ivBuf = new Buffer(128 / 8)
26 | ivBuf.fill(0)
27 | let messageBuf = new Buffer(128 / 8)
28 | messageBuf.fill(0)
29 | let encBuf = Aescbc.encrypt(messageBuf, cipherKeyBuf, ivBuf)
30 | encBuf.length.should.equal(128 / 8 + 128 / 8 + 128 / 8)
31 | })
32 | })
33 |
34 | describe('@decrypt', function () {
35 | it('should decrypt that which was encrypted', function () {
36 | let cipherKeyBuf = new Buffer(256 / 8)
37 | cipherKeyBuf.fill(0x10)
38 | let ivBuf = new Buffer(128 / 8)
39 | ivBuf.fill(0)
40 | let messageBuf = new Buffer(128 / 8)
41 | messageBuf.fill(0)
42 | let encBuf = Aescbc.encrypt(messageBuf, cipherKeyBuf, ivBuf)
43 | let messageBuf2 = Aescbc.decrypt(encBuf, cipherKeyBuf)
44 | messageBuf2.toString('hex').should.equal(messageBuf.toString('hex'))
45 | })
46 | })
47 |
48 | describe('vectors', function () {
49 | vectors.forEach(function (vector, i) {
50 | it('should pass sjcl test vector ' + i, function () {
51 | let keyBuf = new Buffer(vector.key, 'hex')
52 | let ivBuf = new Buffer(vector.iv, 'hex')
53 | let ptbuf = new Buffer(vector.pt, 'hex')
54 | let ctBuf = new Buffer(vector.ct, 'hex')
55 | Aescbc.encrypt(ptbuf, keyBuf, ivBuf).slice(128 / 8).toString('hex').should.equal(vector.ct)
56 | Aescbc.decrypt(Buffer.concat([ivBuf, ctBuf]), keyBuf).toString('hex').should.equal(vector.pt)
57 | })
58 | })
59 | })
60 | })
61 |
--------------------------------------------------------------------------------
/test/base-58-check.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let should = require('chai').should()
4 | let Base58Check = require('../lib/base-58-check')
5 | let base58 = require('../lib/base-58')
6 |
7 | describe('Base58Check', function () {
8 | let buf = new Buffer([0, 1, 2, 3, 253, 254, 255])
9 | let enc = '14HV44ipwoaqfg'
10 |
11 | it('should make an instance with "new"', function () {
12 | let b58 = new Base58Check()
13 | should.exist(b58)
14 | })
15 |
16 | it('should make an instance without "new"', function () {
17 | let b58 = new Base58Check()
18 | should.exist(b58)
19 | })
20 |
21 | it('should allow this handy syntax', function () {
22 | new Base58Check(buf).toString().should.equal(enc)
23 | new Base58Check().fromString(enc).toBuffer().toString('hex').should.equal(buf.toString('hex'))
24 | })
25 |
26 | describe('#fromObject', function () {
27 | it('should set a buf', function () {
28 | should.exist(new Base58Check().fromObject({buf: buf}).buf)
29 | })
30 | })
31 |
32 | describe('@encode', function () {
33 | it('should encode the buffer accurately', function () {
34 | Base58Check.encode(buf).should.equal(enc)
35 | })
36 |
37 | it('should throw an error when the input is not a buffer', function () {
38 | (function () {
39 | Base58Check.encode('string')
40 | }).should.throw('Input must be a buffer')
41 | })
42 | })
43 |
44 | describe('@decode', function () {
45 | it('should decode this encoded value correctly', function () {
46 | Base58Check.decode(enc).toString('hex').should.equal(buf.toString('hex'))
47 | })
48 |
49 | it('should throw an error when input is not a string', function () {
50 | (function () {
51 | Base58Check.decode(5)
52 | }).should.throw('Input must be a string')
53 | })
54 |
55 | it('should throw an error when input is too short', function () {
56 | (function () {
57 | Base58Check.decode(enc.slice(0, 1))
58 | }).should.throw('Input string too short')
59 | })
60 |
61 | it('should throw an error when there is a checksum mismatch', function () {
62 | let buf2 = base58.decode(enc)
63 | buf2[0] = buf2[0] + 1
64 | let enc2 = base58.encode(buf2)
65 | ;(function () {
66 | Base58Check.decode(enc2)
67 | }).should.throw('Checksum mismatch')
68 | })
69 | })
70 |
71 | describe('#fromHex', function () {
72 | it('should set buffer from hex', function () {
73 | let b58 = new Base58Check().fromHex(buf.toString('hex'))
74 | b58.buf.toString('hex').should.equal(buf.toString('hex'))
75 | })
76 | })
77 |
78 | describe('#fromBuffer', function () {
79 | it('should not fail', function () {
80 | should.exist(new Base58Check().fromBuffer(buf))
81 | })
82 |
83 | it('should set buffer', function () {
84 | let b58 = new Base58Check().fromBuffer(buf)
85 | b58.buf.toString('hex').should.equal(buf.toString('hex'))
86 | })
87 | })
88 |
89 | describe('#fromString', function () {
90 | it('should convert this known string to a buffer', function () {
91 | new Base58Check().fromString(enc).toBuffer().toString('hex').should.equal(buf.toString('hex'))
92 | })
93 | })
94 |
95 | describe('#toHex', function () {
96 | it('should return the buffer', function () {
97 | let b58 = new Base58Check(buf)
98 | b58.toHex().should.equal(buf.toString('hex'))
99 | })
100 | })
101 |
102 | describe('#toBuffer', function () {
103 | it('should return the buffer', function () {
104 | let b58 = new Base58Check(buf)
105 | b58.toBuffer().toString('hex').should.equal(buf.toString('hex'))
106 | })
107 | })
108 |
109 | describe('#toString', function () {
110 | it('should return the buffer', function () {
111 | let b58 = new Base58Check(buf)
112 | b58.toString().should.equal(enc)
113 | })
114 | })
115 | })
116 |
--------------------------------------------------------------------------------
/test/base-58.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let Base58 = require('../lib/base-58')
4 | let should = require('chai').should()
5 |
6 | describe('Base58', function () {
7 | let buf = new Buffer([0, 1, 2, 3, 253, 254, 255])
8 | let enc = '1W7N4RuG'
9 |
10 | it('should make an instance with "new"', function () {
11 | let b58 = new Base58()
12 | should.exist(b58)
13 | })
14 |
15 | it('should make an instance without "new"', function () {
16 | let b58 = new Base58()
17 | should.exist(b58)
18 | })
19 |
20 | it('should allow this handy syntax', function () {
21 | new Base58(buf).toString().should.equal(enc)
22 | new Base58().fromString(enc).toBuffer().toString('hex').should.equal(buf.toString('hex'))
23 | })
24 |
25 | describe('#fromObject', function () {
26 | it('should set a blank buffer', function () {
27 | new Base58().fromObject({buf: new Buffer([])})
28 | })
29 | })
30 |
31 | describe('@encode', function () {
32 | it('should encode the buffer accurately', function () {
33 | Base58.encode(buf).should.equal(enc)
34 | })
35 |
36 | it('should throw an error when the Input is not a buffer', function () {
37 | (function () {
38 | Base58.encode('string')
39 | }).should.throw('Input should be a buffer')
40 | })
41 | })
42 |
43 | describe('@decode', function () {
44 | it('should decode this encoded value correctly', function () {
45 | Base58.decode(enc).toString('hex').should.equal(buf.toString('hex'))
46 | Buffer.isBuffer(Base58.decode(enc)).should.equal(true)
47 | })
48 |
49 | it('should throw an error when Input is not a string', function () {
50 | (function () {
51 | Base58.decode(5)
52 | }).should.throw('Input should be a string')
53 | })
54 | })
55 |
56 | describe('#fromHex', function () {
57 | it('should set buffer', function () {
58 | let b58 = new Base58().fromHex(buf.toString('hex'))
59 | b58.buf.toString('hex').should.equal(buf.toString('hex'))
60 | })
61 | })
62 |
63 | describe('#fromBuffer', function () {
64 | it('should not fail', function () {
65 | should.exist(new Base58().fromBuffer(buf))
66 | })
67 |
68 | it('should set buffer', function () {
69 | let b58 = new Base58().fromBuffer(buf)
70 | b58.buf.toString('hex').should.equal(buf.toString('hex'))
71 | })
72 | })
73 |
74 | describe('#fromString', function () {
75 | it('should convert this known string to a buffer', function () {
76 | new Base58().fromString(enc).toBuffer().toString('hex').should.equal(buf.toString('hex'))
77 | })
78 | })
79 |
80 | describe('#toHex', function () {
81 | it('should return the buffer in hex', function () {
82 | let b58 = new Base58(buf)
83 | b58.toHex().should.equal(buf.toString('hex'))
84 | })
85 | })
86 |
87 | describe('#toBuffer', function () {
88 | it('should return the buffer', function () {
89 | let b58 = new Base58(buf)
90 | b58.toBuffer().toString('hex').should.equal(buf.toString('hex'))
91 | })
92 | })
93 |
94 | describe('#toString', function () {
95 | it('should return the buffer', function () {
96 | let b58 = new Base58(buf)
97 | b58.toString().should.equal(enc)
98 | })
99 | })
100 | })
101 |
--------------------------------------------------------------------------------
/test/bip-68.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let Bip68 = require('../lib/bip-68')
4 | let should = require('chai').should()
5 |
6 | describe('Bip68', function () {
7 | it('should exist', function () {
8 | should.exist(Bip68)
9 | should.exist(new Bip68())
10 | })
11 |
12 | describe('@nSequence2Height', function () {
13 | it('should convert nSequence to height', function () {
14 | Bip68.nSequence2Height(0xffffffff).should.equal(0x0000ffff)
15 | })
16 | })
17 |
18 | describe('@height2NSequence', function () {
19 | it('should convert height to nSequence', function () {
20 | Bip68.height2NSequence(0x0000ffff).should.equal(0x0000ffff)
21 | })
22 | })
23 |
24 | describe('@nSequence2Time', function () {
25 | it('should convert nSequence to time', function () {
26 | Bip68.nSequence2Time(0x0000000f).should.equal(0x0000000f << 9)
27 | Bip68.nSequence2Time(0x0fffffff).should.equal(0x0000ffff << 9)
28 | })
29 | })
30 |
31 | describe('@time2NSequence', function () {
32 | it('should convert time to nSequence', function () {
33 | Bip68.time2NSequence(0x00000001 << 9).should.equal(0x00000001 | (1 << 22))
34 | Bip68.time2NSequence(0x000000ff << 9).should.equal(0x000000ff | (1 << 22))
35 | })
36 | })
37 |
38 | describe('@nSequenceIsDisabled', function () {
39 | it('should know if nSequence interpretation as lock time is disabled', function () {
40 | Bip68.nSequenceIsDisabled(1 << 31).should.equal(true)
41 | Bip68.nSequenceIsDisabled(1 << 30).should.equal(false)
42 | })
43 | })
44 |
45 | describe('@nSequenceIsTime', function () {
46 | it('should know if nSequence is time', function () {
47 | Bip68.nSequenceIsTime(1 << 22).should.equal(true)
48 | Bip68.nSequenceIsTime(1 << 21).should.equal(false)
49 | })
50 | })
51 |
52 | describe('@nSequenceValue', function () {
53 | it('should get the value', function () {
54 | Bip68.nSequenceValue(0xfffffff).should.equal(0x0000ffff)
55 | })
56 | })
57 | })
58 |
--------------------------------------------------------------------------------
/test/block-header.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let BlockHeader = require('../lib/block-header')
4 | let Bw = require('../lib/bw')
5 | let Br = require('../lib/br')
6 | let should = require('chai').should()
7 |
8 | describe('BlockHeader', function () {
9 | let bh = new BlockHeader()
10 | let versionBytesNum = 1
11 | let prevBlockHashBuf = new Buffer(32)
12 | prevBlockHashBuf.fill(5)
13 | let merkleRootBuf = new Buffer(32)
14 | merkleRootBuf.fill(9)
15 | let time = 2
16 | let bits = 3
17 | let nonce = 4
18 | bh.fromObject({
19 | versionBytesNum: versionBytesNum,
20 | prevBlockHashBuf: prevBlockHashBuf,
21 | merkleRootBuf: merkleRootBuf,
22 | time: time,
23 | bits: bits,
24 | nonce: nonce
25 | })
26 | let bhhex = '0100000005050505050505050505050505050505050505050505050505050505050505050909090909090909090909090909090909090909090909090909090909090909020000000300000004000000'
27 | let bhbuf = new Buffer(bhhex, 'hex')
28 |
29 | it('should make a new blockHeader', function () {
30 | let blockHeader = new BlockHeader()
31 | should.exist(blockHeader)
32 | blockHeader = new BlockHeader()
33 | should.exist(blockHeader)
34 | })
35 |
36 | describe('#fromObject', function () {
37 | it('should set all the variables', function () {
38 | bh.fromObject({
39 | versionBytesNum: versionBytesNum,
40 | prevBlockHashBuf: prevBlockHashBuf,
41 | merkleRootBuf: merkleRootBuf,
42 | time: time,
43 | bits: bits,
44 | nonce: nonce
45 | })
46 | should.exist(bh.versionBytesNum)
47 | should.exist(bh.prevBlockHashBuf)
48 | should.exist(bh.merkleRootBuf)
49 | should.exist(bh.time)
50 | should.exist(bh.bits)
51 | should.exist(bh.nonce)
52 | })
53 | })
54 |
55 | describe('#fromJSON', function () {
56 | it('should set all the variables', function () {
57 | let bh = new BlockHeader().fromJSON({
58 | versionBytesNum: versionBytesNum,
59 | prevBlockHashBuf: prevBlockHashBuf.toString('hex'),
60 | merkleRootBuf: merkleRootBuf.toString('hex'),
61 | time: time,
62 | bits: bits,
63 | nonce: nonce
64 | })
65 | should.exist(bh.versionBytesNum)
66 | should.exist(bh.prevBlockHashBuf)
67 | should.exist(bh.merkleRootBuf)
68 | should.exist(bh.time)
69 | should.exist(bh.bits)
70 | should.exist(bh.nonce)
71 | })
72 | })
73 |
74 | describe('#toJSON', function () {
75 | it('should set all the variables', function () {
76 | let json = bh.toJSON()
77 | should.exist(json.versionBytesNum)
78 | should.exist(json.prevBlockHashBuf)
79 | should.exist(json.merkleRootBuf)
80 | should.exist(json.time)
81 | should.exist(json.bits)
82 | should.exist(json.nonce)
83 | })
84 | })
85 |
86 | describe('#fromHex', function () {
87 | it('should parse this known hex string', function () {
88 | new BlockHeader().fromHex(bhhex).toBuffer().toString('hex').should.equal(bhhex)
89 | })
90 | })
91 |
92 | describe('#fromBuffer', function () {
93 | it('should parse this known buffer', function () {
94 | new BlockHeader().fromBuffer(bhbuf).toBuffer().toString('hex').should.equal(bhhex)
95 | })
96 | })
97 |
98 | describe('#fromBr', function () {
99 | it('should parse this known buffer', function () {
100 | new BlockHeader().fromBr(new Br(bhbuf)).toBuffer().toString('hex').should.equal(bhhex)
101 | })
102 | })
103 |
104 | describe('#toHex', function () {
105 | it('should output this known hex string', function () {
106 | new BlockHeader().fromBuffer(bhbuf).toHex().should.equal(bhhex)
107 | })
108 | })
109 |
110 | describe('#toBuffer', function () {
111 | it('should output this known buffer', function () {
112 | new BlockHeader().fromBuffer(bhbuf).toBuffer().toString('hex').should.equal(bhhex)
113 | })
114 | })
115 |
116 | describe('#toBw', function () {
117 | it('should output this known buffer', function () {
118 | new BlockHeader().fromBuffer(bhbuf).toBw().toBuffer().toString('hex').should.equal(bhhex)
119 | let bw = new Bw()
120 | new BlockHeader().fromBuffer(bhbuf).toBw(bw)
121 | bw.toBuffer().toString('hex').should.equal(bhhex)
122 | })
123 | })
124 | })
125 |
--------------------------------------------------------------------------------
/test/cmp.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let cmp = require('../lib/cmp')
4 | require('chai').should()
5 |
6 | describe('cmp', function () {
7 | it('should know if these buffers are equal', function () {
8 | let buf1, buf2
9 |
10 | buf1 = new Buffer([])
11 | buf2 = new Buffer([])
12 | cmp(buf1, buf2).should.equal(true)
13 |
14 | buf1 = new Buffer([1])
15 | buf2 = new Buffer([])
16 | cmp(buf1, buf2).should.equal(false)
17 |
18 | buf1 = new Buffer([])
19 | buf2 = new Buffer([1])
20 | cmp(buf1, buf2).should.equal(false)
21 |
22 | buf1 = new Buffer([1])
23 | buf2 = new Buffer([1])
24 | cmp(buf1, buf2).should.equal(true)
25 |
26 | buf1 = new Buffer([1, 1])
27 | buf2 = new Buffer([1])
28 | cmp(buf1, buf2).should.equal(false)
29 |
30 | buf1 = new Buffer([1])
31 | buf2 = new Buffer([1, 1])
32 | cmp(buf1, buf2).should.equal(false)
33 |
34 | buf1 = new Buffer([1, 1])
35 | buf2 = new Buffer([1, 1])
36 | cmp(buf1, buf2).should.equal(true)
37 |
38 | buf1 = new Buffer([1, 0])
39 | buf2 = new Buffer([1, 1])
40 | cmp(buf1, buf2).should.equal(false)
41 |
42 | buf1 = new Buffer([1])
43 | buf2 = new Buffer([1, 0])
44 | cmp(buf1, buf2).should.equal(false)
45 | ;(function () {
46 | let buf1 = ''
47 | let buf2 = new Buffer([0])
48 | cmp(buf1, buf2)
49 | }).should.throw('buf1 and buf2 must be buffers')
50 | ;(function () {
51 | let buf1 = new Buffer([0])
52 | let buf2 = ''
53 | cmp(buf1, buf2)
54 | }).should.throw('buf1 and buf2 must be buffers')
55 | })
56 | })
57 |
--------------------------------------------------------------------------------
/test/ecies.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let Ecies = require('../lib/ecies')
4 | let should = require('chai').should()
5 | let KeyPair = require('../lib/key-pair')
6 | let Hash = require('../lib/hash')
7 | let asink = require('asink')
8 |
9 | describe('#Ecies', function () {
10 | it('should make a new Ecies object', function () {
11 | should.exist(Ecies)
12 | })
13 |
14 | let fromkey = new KeyPair().fromRandom()
15 | let tokey = new KeyPair().fromRandom()
16 | let messageBuf = Hash.sha256(new Buffer('my message is the hash of this string'))
17 |
18 | describe('@encrypt', function () {
19 | it('should return a buffer', function () {
20 | let encBuf = Ecies.encrypt(messageBuf, tokey.pubKey, fromkey)
21 | Buffer.isBuffer(encBuf).should.equal(true)
22 | })
23 |
24 | it('should return a buffer if fromkey is not present', function () {
25 | let encBuf = Ecies.encrypt(messageBuf, tokey.pubKey)
26 | Buffer.isBuffer(encBuf).should.equal(true)
27 | })
28 | })
29 |
30 | describe('@asyncEncrypt', function () {
31 | it('should return a buffer', function () {
32 | return asink(function * () {
33 | let encBuf = yield Ecies.asyncEncrypt(messageBuf, tokey.pubKey, fromkey)
34 | Buffer.isBuffer(encBuf).should.equal(true)
35 | }, this)
36 | })
37 |
38 | it('should return a buffer if fromkey is not present', function () {
39 | return asink(function * () {
40 | let encBuf = yield Ecies.asyncEncrypt(messageBuf, tokey.pubKey)
41 | Buffer.isBuffer(encBuf).should.equal(true)
42 | }, this)
43 | })
44 | })
45 |
46 | describe('@decrypt', function () {
47 | it('should decrypt that which was encrypted', function () {
48 | let encBuf = Ecies.encrypt(messageBuf, tokey.pubKey, fromkey)
49 | let messageBuf2 = Ecies.decrypt(encBuf, tokey.privKey)
50 | messageBuf2.toString('hex').should.equal(messageBuf.toString('hex'))
51 | })
52 |
53 | it('should decrypt that which was encrypted if fromKeyPair was randomly generated', function () {
54 | let encBuf = Ecies.encrypt(messageBuf, tokey.pubKey)
55 | let messageBuf2 = Ecies.decrypt(encBuf, tokey.privKey)
56 | messageBuf2.toString('hex').should.equal(messageBuf.toString('hex'))
57 | })
58 | })
59 |
60 | describe('@asyncDecrypt', function () {
61 | it('should decrypt that which was encrypted', function () {
62 | return asink(function * () {
63 | let encBuf = yield Ecies.asyncEncrypt(messageBuf, tokey.pubKey, fromkey)
64 | let messageBuf2 = Ecies.decrypt(encBuf, tokey.privKey)
65 | messageBuf2.toString('hex').should.equal(messageBuf.toString('hex'))
66 | }, this)
67 | })
68 |
69 | it('should decrypt that which was encrypted if fromKeyPair was randomly generated', function () {
70 | return asink(function * () {
71 | let encBuf = yield Ecies.asyncEncrypt(messageBuf, tokey.pubKey)
72 | let messageBuf2 = Ecies.decrypt(encBuf, tokey.privKey)
73 | messageBuf2.toString('hex').should.equal(messageBuf.toString('hex'))
74 | }, this)
75 | })
76 | })
77 | })
78 |
--------------------------------------------------------------------------------
/test/get-blocks.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let GetBlocks = require('../lib/get-blocks')
4 | let should = require('chai').should()
5 |
6 | describe('GetBlocks', function () {
7 | it('should exist', function () {
8 | should.exist(GetBlocks)
9 | should.exist(new GetBlocks())
10 | })
11 |
12 | describe('#toBuffer', function () {
13 | it('should convert to a buffer', function () {
14 | let buf = new Buffer(32)
15 | buf.fill(0)
16 | let hashes = [buf]
17 | let getblocks = new GetBlocks().fromHashes(hashes)
18 | let getblocksbuf = getblocks.toBuffer()
19 | getblocksbuf.length.should.equal(4 + 1 + 0 + 32)
20 | })
21 | })
22 |
23 | describe('#fromBuffer', function () {
24 | it('should convert from a buffer', function () {
25 | let buf = new Buffer(32)
26 | buf.fill(0)
27 | let hashes = [buf]
28 | let getblocks = new GetBlocks().fromHashes(hashes)
29 | let getblocksbuf = getblocks.toBuffer()
30 | let getblocks2 = new GetBlocks().fromBuffer(getblocksbuf)
31 | should.exist(getblocks2.versionBytesNum)
32 | should.exist(getblocks2.hashBufsVi)
33 | should.exist(getblocks2.hashBufs)
34 | should.exist(getblocks2.stopHashBuf)
35 | })
36 | })
37 |
38 | describe('#fromHashes', function () {
39 | it('should convert from a list of one hash', function () {
40 | let buf = new Buffer(32)
41 | buf.fill(0)
42 | let hashes = [buf]
43 | let getblocks = new GetBlocks().fromHashes(hashes)
44 | should.exist(getblocks)
45 | getblocks.hashBufs.length.should.equal(0)
46 | should.exist(getblocks.stopHashBuf)
47 | })
48 |
49 | it('should convert from a list of two hashes', function () {
50 | let buf = new Buffer(32)
51 | buf.fill(0)
52 | let hashes = [buf, buf]
53 | let getblocks = new GetBlocks().fromHashes(hashes)
54 | should.exist(getblocks)
55 | getblocks.hashBufs.length.should.equal(1)
56 | should.exist(getblocks.stopHashBuf)
57 | })
58 | })
59 |
60 | describe('@fromHashes', function () {
61 | it('should convert from a list of one hash', function () {
62 | let buf = new Buffer(32)
63 | buf.fill(0)
64 | let hashes = [buf]
65 | let getblocks = GetBlocks.fromHashes(hashes)
66 | should.exist(getblocks)
67 | getblocks.hashBufs.length.should.equal(0)
68 | should.exist(getblocks.stopHashBuf)
69 | })
70 |
71 | it('should convert from a list of two hashes', function () {
72 | let buf = new Buffer(32)
73 | buf.fill(0)
74 | let hashes = [buf, buf]
75 | let getblocks = GetBlocks.fromHashes(hashes)
76 | should.exist(getblocks)
77 | getblocks.hashBufs.length.should.equal(1)
78 | should.exist(getblocks.stopHashBuf)
79 | })
80 | })
81 |
82 | describe('#toHashes', function () {
83 | it('should give a list of hashes', function () {
84 | let buf = new Buffer(32)
85 | buf.fill(0)
86 | let hashes = [buf, buf]
87 | let getblocks = new GetBlocks().fromHashes(hashes)
88 | let hashes2 = getblocks.toHashes()
89 | hashes2.length.should.equal(2)
90 | })
91 | })
92 | })
93 |
--------------------------------------------------------------------------------
/test/global.js:
--------------------------------------------------------------------------------
1 | /* global after */
2 | /**
3 | * Global "before" and "after" to run before and after all tests. These can be
4 | * used to establish and also tear down global database connections, network
5 | * connections, and worker connections. It's important not to leave thins
6 | * hanging when the tests are done running so that the tests end properly.
7 | */
8 | 'use strict'
9 | let Workers = require('../lib/workers')
10 |
11 | after(function () {
12 | Workers.endGlobalWorkers()
13 | })
14 |
--------------------------------------------------------------------------------
/test/helpers/interp.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | let Interp = require('../../lib/interp')
3 | let Script = require('../../lib/script')
4 | let Tx = require('../../lib/tx')
5 | let Bn = require('../../lib/bn')
6 |
7 | module.exports.testInterpPartial = function testInterpPartial (it, scriptValid, scriptInvalid, mod = 0) {
8 | let c
9 |
10 | c = 0
11 | scriptValid.forEach(function (vector, i) {
12 | if (vector.length === 1) {
13 | return
14 | }
15 | c++
16 | if ((c + mod) % 4) {
17 | return
18 | }
19 | it('should verify scriptValid vector ' + c, function () {
20 | let scriptSig = new Script().fromBitcoindString(vector[0])
21 | let scriptPubKey = new Script().fromBitcoindString(vector[1])
22 | let flags = Interp.getFlags(vector[2])
23 |
24 | let hashBuf = new Buffer(32)
25 | hashBuf.fill(0)
26 | let credtx = new Tx()
27 | credtx.addTxIn(hashBuf, 0xffffffff, new Script().writeString('OP_0 OP_0'), 0xffffffff)
28 | credtx.addTxOut(new Bn(0), scriptPubKey)
29 |
30 | let idbuf = credtx.hash()
31 | let spendtx = new Tx()
32 | spendtx.addTxIn(idbuf, 0, scriptSig, 0xffffffff)
33 | spendtx.addTxOut(new Bn(0), new Script())
34 |
35 | let interp = new Interp()
36 | let verified = interp.verify(scriptSig, scriptPubKey, spendtx, 0, flags)
37 | verified.should.equal(true)
38 | })
39 | })
40 |
41 | c = 0
42 | scriptInvalid.forEach(function (vector, i) {
43 | if (vector.length === 1) {
44 | return
45 | }
46 | c++
47 | if ((c + mod) % 4) {
48 | return
49 | }
50 | it('should unverify scriptInvalid vector ' + c, function () {
51 | let scriptSig = new Script().fromBitcoindString(vector[0])
52 | let scriptPubKey = new Script().fromBitcoindString(vector[1])
53 | let flags = Interp.getFlags(vector[2])
54 |
55 | let hashBuf = new Buffer(32)
56 | hashBuf.fill(0)
57 | let credtx = new Tx()
58 | credtx.addTxIn(hashBuf, 0xffffffff, new Script().writeString('OP_0 OP_0'), 0xffffffff)
59 | credtx.addTxOut(new Bn(0), scriptPubKey)
60 |
61 | let idbuf = credtx.hash()
62 | let spendtx = new Tx()
63 | spendtx.addTxIn(idbuf, 0, scriptSig, 0xffffffff)
64 | spendtx.addTxOut(new Bn(0), new Script())
65 |
66 | let interp = new Interp()
67 | let verified = interp.verify(scriptSig, scriptPubKey, spendtx, 0, flags)
68 | verified.should.equal(false)
69 | })
70 | })
71 | }
72 |
--------------------------------------------------------------------------------
/test/index.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let should = require('chai').should()
4 | let YoursBitcoin = require('../')
5 |
6 | describe('yours-bitcoin', function () {
7 | it('should pass this sanity check on loading the main package', function () {
8 | should.exist(YoursBitcoin)
9 | })
10 | })
11 |
--------------------------------------------------------------------------------
/test/interp-vectors-1.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let scriptValid = require('./vectors/bitcoind/script_valid')
4 | let scriptInvalid = require('./vectors/bitcoind/script_invalid')
5 | let testInterpPartial = require('./helpers/interp').testInterpPartial
6 |
7 | describe('Interp Vectors 1/4', function () {
8 | testInterpPartial(it, scriptValid, scriptInvalid, 0)
9 | })
10 |
--------------------------------------------------------------------------------
/test/interp-vectors-2.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let scriptValid = require('./vectors/bitcoind/script_valid')
4 | let scriptInvalid = require('./vectors/bitcoind/script_invalid')
5 | let testInterpPartial = require('./helpers/interp').testInterpPartial
6 |
7 | describe('Interp Vectors 2/4', function () {
8 | testInterpPartial(it, scriptValid, scriptInvalid, 1)
9 | })
10 |
--------------------------------------------------------------------------------
/test/interp-vectors-3.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let scriptValid = require('./vectors/bitcoind/script_valid')
4 | let scriptInvalid = require('./vectors/bitcoind/script_invalid')
5 | let testInterpPartial = require('./helpers/interp').testInterpPartial
6 |
7 | describe('Interp Vectors 3/4', function () {
8 | testInterpPartial(it, scriptValid, scriptInvalid, 2)
9 | })
10 |
--------------------------------------------------------------------------------
/test/interp-vectors-4.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let scriptValid = require('./vectors/bitcoind/script_valid')
4 | let scriptInvalid = require('./vectors/bitcoind/script_invalid')
5 | let testInterpPartial = require('./helpers/interp').testInterpPartial
6 |
7 | describe('Interp Vectors 4/4', function () {
8 | testInterpPartial(it, scriptValid, scriptInvalid, 3)
9 | })
10 |
--------------------------------------------------------------------------------
/test/inv.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let Inv = require('../lib/inv')
4 | let Hash = require('../lib/hash')
5 | let Bw = require('../lib/bw')
6 | let should = require('chai').should()
7 |
8 | describe('Inv', function () {
9 | it('should exist', function () {
10 | let inv = new Inv()
11 | should.exist(inv)
12 | should.exist(Inv)
13 | })
14 |
15 | describe('#fromBuffer', function () {
16 | it('should convert from a buffer', function () {
17 | let hashBuf = Hash.sha256(new Buffer(0))
18 | let typeNum = 1
19 | let typebuf = new Bw().writeUInt32LE(typeNum).toBuffer()
20 | let buf = Buffer.concat([typebuf, hashBuf])
21 | let inv = new Inv().fromBuffer(buf)
22 | inv.typeNum.should.equal(typeNum)
23 | Buffer.compare(inv.hashBuf, hashBuf).should.equal(0)
24 | })
25 | })
26 |
27 | describe('#toBuffer', function () {
28 | it('should convert to a buffer', function () {
29 | let hashBuf = Hash.sha256(new Buffer(0))
30 | let typeNum = 1
31 | let typebuf = new Bw().writeUInt32LE(typeNum).toBuffer()
32 | let buf = Buffer.concat([typebuf, hashBuf])
33 | let inv = new Inv().fromBuffer(buf)
34 | let buf2 = inv.toBuffer()
35 | Buffer.compare(buf, buf2).should.equal(0)
36 | })
37 | })
38 |
39 | describe('#isTx', function () {
40 | it('should know this is a tx hash', function () {
41 | let hashBuf = Hash.sha256(new Buffer(0))
42 | let typeNum = Inv.MSG_TX
43 | let inv = new Inv(typeNum, hashBuf)
44 | inv.isTx().should.equal(true)
45 | })
46 | })
47 |
48 | describe('#isBlock', function () {
49 | it('should know this is a block hash', function () {
50 | let hashBuf = Hash.sha256(new Buffer(0))
51 | let typeNum = Inv.MSG_BLOCK
52 | let inv = new Inv(typeNum, hashBuf)
53 | inv.isBlock().should.equal(true)
54 | })
55 | })
56 |
57 | describe('#isFilteredBlock', function () {
58 | it('should know this is a filtered block hash', function () {
59 | let hashBuf = Hash.sha256(new Buffer(0))
60 | let typeNum = Inv.MSG_FILTERED_BLOCK
61 | let inv = new Inv(typeNum, hashBuf)
62 | inv.isFilteredBlock().should.equal(true)
63 | })
64 | })
65 | })
66 |
--------------------------------------------------------------------------------
/test/kdf.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | require('chai').should()
4 | let Kdf = require('../lib/kdf')
5 | let Hash = require('../lib/hash')
6 | let vectors = require('./vectors/kdf')
7 |
8 | describe('Kdf', function () {
9 | it('should satisfy this basic API', function () {
10 | Kdf.Testnet.should.equal(Kdf.Testnet)
11 | Kdf.Mainnet.should.equal(Kdf.Mainnet)
12 | Kdf.Mainnet.should.not.equal(Kdf.Testnet)
13 | })
14 |
15 | describe('@Pbkdf2', function () {
16 | it('should return values of the right size', function () {
17 | let passBuf = new Buffer([0])
18 | let saltBuf = new Buffer([0])
19 | let key1 = Kdf.Pbkdf2(passBuf, saltBuf)
20 | key1.length.should.equal(512 / 8)
21 | let key2 = Kdf.Pbkdf2(passBuf, saltBuf, 2)
22 | key2.length.should.equal(512 / 8)
23 | key1.toString('hex').should.not.equal(key2.toString('hex'))
24 | let key3 = Kdf.Pbkdf2(passBuf, saltBuf, 2, 1024)
25 | key3.length.should.equal(1024 / 8)
26 | let key4 = Kdf.Pbkdf2(passBuf, saltBuf, 2, 256, 'sha256')
27 | key4.length.should.equal(256 / 8)
28 | })
29 |
30 | // Test vectors from: http://tools.ietf.org/html/rfc6070#section-2
31 | vectors.PBKDF2.valid.forEach(function (obj, i) {
32 | it('should work for Pbkdf2 test vector ' + i, function () {
33 | let passBuf = new Buffer(obj.p, 'hex')
34 | let saltBuf = new Buffer(obj.s, 'hex')
35 | let nIterations = obj.c
36 | let keyLenBits = obj.dkLen * 8
37 | let hmacf = obj.hmacf
38 | let key = Kdf.Pbkdf2(passBuf, saltBuf, nIterations, keyLenBits, hmacf)
39 | key.toString('hex').should.equal(obj.key)
40 | })
41 | })
42 | })
43 |
44 | describe('@buf2KeyPair', function () {
45 | it('should compute these known values', function () {
46 | let buf = Hash.sha256(new Buffer('test'))
47 | let keyPair = Kdf.buf2KeyPair(buf)
48 | keyPair.privKey.toString().should.equal('KxxVszVMFLGzmxpxR7sMSaWDmqMKLVhKebX5vZbGHyuR8spreQ7V')
49 | keyPair.pubKey.toString().should.equal('03774f761ae89a0d2fda0d532bad62286ae8fcda9bc38c060036296085592a97c1')
50 | })
51 | })
52 |
53 | describe('@sha256Hmac2KeyPair', function () {
54 | it('should compute these known values', function () {
55 | let buf = Hash.sha256(new Buffer('test'))
56 | let keyPair = Kdf.sha256Hmac2KeyPair(buf)
57 | keyPair.privKey.toString().should.equal('KxxVszVMFLGzmxpxR7sMSaWDmqMKLVhKebX5vZbGHyuR8spreQ7V')
58 | keyPair.pubKey.toString().should.equal('03774f761ae89a0d2fda0d532bad62286ae8fcda9bc38c060036296085592a97c1')
59 | })
60 | })
61 |
62 | describe('@sha256Hmac2PrivKey', function () {
63 | it('should compute this known privKey', function () {
64 | let buf = Hash.sha256(new Buffer('test'))
65 | let privKey = Kdf.sha256Hmac2PrivKey(buf)
66 | privKey.toString().should.equal('KxxVszVMFLGzmxpxR7sMSaWDmqMKLVhKebX5vZbGHyuR8spreQ7V')
67 | })
68 | })
69 | })
70 |
--------------------------------------------------------------------------------
/test/msg-addr.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let Addr = require('../lib/addr')
4 | let MsgAddr = require('../lib/msg-addr')
5 | let asink = require('asink')
6 | let should = require('chai').should()
7 |
8 | describe('MsgAddr', function () {
9 | let addrhex = 'e8030000000000000000000000000000000000000000000000000000208d'
10 |
11 | it('should exist', function () {
12 | should.exist(MsgAddr)
13 | should.exist(new MsgAddr())
14 | })
15 |
16 | describe('#fromAddrs', function () {
17 | it('should convert from addrs', function () {
18 | let addr = new Addr().fromHex(addrhex)
19 | let msgaddr = new MsgAddr().fromAddrs([addr])
20 | msgaddr.getCmd().should.equal('addr')
21 | msgaddr.dataBuf.length.should.equal(1 + addrhex.length / 2)
22 | })
23 | })
24 |
25 | describe('@fromAddrs', function () {
26 | it('should convert from addrs', function () {
27 | let addr = Addr.fromHex(addrhex)
28 | let msgaddr = MsgAddr.fromAddrs([addr])
29 | msgaddr.getCmd().should.equal('addr')
30 | msgaddr.dataBuf.length.should.equal(1 + addrhex.length / 2)
31 | })
32 | })
33 |
34 | describe('#asyncFromAddrs', function () {
35 | it('should convert from addrs', function () {
36 | return asink(function * () {
37 | let addr = new Addr().fromHex(addrhex)
38 | let msgaddr = yield new MsgAddr().asyncFromAddrs([addr])
39 | msgaddr.getCmd().should.equal('addr')
40 | msgaddr.dataBuf.length.should.equal(1 + addrhex.length / 2)
41 | }, this)
42 | })
43 | })
44 |
45 | describe('@asyncFromAddrs', function () {
46 | it('should convert from addrs', function () {
47 | return asink(function * () {
48 | let addr = new Addr().fromHex(addrhex)
49 | let msgaddr = yield MsgAddr.asyncFromAddrs([addr])
50 | msgaddr.getCmd().should.equal('addr')
51 | msgaddr.dataBuf.length.should.equal(1 + addrhex.length / 2)
52 | }, this)
53 | })
54 | })
55 |
56 | describe('#toAddrs', function () {
57 | it('should convert to addrs', function () {
58 | let addr = new Addr().fromHex(addrhex)
59 | let msgaddr = new MsgAddr().fromAddrs([addr])
60 | let addrs2 = msgaddr.toAddrs()
61 | addrs2.length.should.equal(1)
62 | ;(addrs2[0] instanceof Addr).should.equal(true)
63 | })
64 |
65 | it('should convert to multiple addrs', function () {
66 | let addr = new Addr().fromHex(addrhex)
67 | let msgaddr = new MsgAddr().fromAddrs([addr, addr, addr])
68 | let addrs2 = msgaddr.toAddrs()
69 | addrs2.length.should.equal(3)
70 | ;(addrs2[0] instanceof Addr).should.equal(true)
71 | })
72 | })
73 |
74 | describe('#isValid', function () {
75 | it('should know this is a valid msg addrs', function () {
76 | let addr = new Addr().fromHex(addrhex)
77 | let msgaddr = new MsgAddr().fromAddrs([addr])
78 | msgaddr.isValid().should.equal(true)
79 | })
80 | })
81 | })
82 |
--------------------------------------------------------------------------------
/test/msg-alert.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let MsgAlert = require('../lib/msg-alert')
4 | let should = require('chai').should()
5 |
6 | describe('MsgAlert', function () {
7 | it('should exist', function () {
8 | should.exist(MsgAlert)
9 | should.exist(new MsgAlert())
10 | })
11 |
12 | describe('#isValid', function () {
13 | it('should know this is a possibly-valid msgalert', function () {
14 | let msgalert = new MsgAlert()
15 | .setData(new Buffer(0))
16 | msgalert.isValid().should.equal(true)
17 | })
18 | })
19 | })
20 |
--------------------------------------------------------------------------------
/test/msg-block.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let Block = require('../lib/block')
4 | let MsgBlock = require('../lib/msg-block')
5 | let asink = require('asink')
6 | let should = require('chai').should()
7 |
8 | describe('MsgBlock', function () {
9 | let blockhex = 'f9beb4d93200000001000000050505050505050505050505050505050505050505050505050505050505050509090909090909090909090909090909090909090909090909090909090909090200000003000000040000000101000000029e8d016a7b0dc49a325922d05da1f916d1e4d4f0cb840c9727f3d22ce8d1363f000000008c493046022100e9318720bee5425378b4763b0427158b1051eec8b08442ce3fbfbf7b30202a44022100d4172239ebd701dae2fbaaccd9f038e7ca166707333427e3fb2a2865b19a7f27014104510c67f46d2cbb29476d1f0b794be4cb549ea59ab9cc1e731969a7bf5be95f7ad5e7f904e5ccf50a9dc1714df00fbeb794aa27aaff33260c1032d931a75c56f2ffffffffa3195e7a1ab665473ff717814f6881485dc8759bebe97e31c301ffe7933a656f020000008b48304502201c282f35f3e02a1f32d2089265ad4b561f07ea3c288169dedcf2f785e6065efa022100e8db18aadacb382eed13ee04708f00ba0a9c40e3b21cf91da8859d0f7d99e0c50141042b409e1ebbb43875be5edde9c452c82c01e3903d38fa4fd89f3887a52cb8aea9dc8aec7e2c9d5b3609c03eb16259a2537135a1bf0f9c5fbbcbdbaf83ba402442ffffffff02206b1000000000001976a91420bb5c3bfaef0231dc05190e7f1c8e22e098991e88acf0ca0100000000001976a9149e3e2d23973a04ec1b02be97c30ab9f2f27c3b2c88ac00000000'
10 |
11 | it('should exist', function () {
12 | let msgblock = new MsgBlock()
13 | should.exist(MsgBlock)
14 | should.exist(msgblock)
15 | })
16 |
17 | describe('#fromBlock', function () {
18 | it('should convert a block into a msgblock', function () {
19 | let block = new Block().fromHex(blockhex)
20 | let msgblock = new MsgBlock().fromBlock(block)
21 | msgblock.isValid().should.equal(true)
22 | })
23 | })
24 |
25 | describe('@fromBlock', function () {
26 | it('should convert a block into a msgblock', function () {
27 | let block = Block.fromHex(blockhex)
28 | let msgblock = MsgBlock.fromBlock(block)
29 | msgblock.isValid().should.equal(true)
30 | })
31 | })
32 |
33 | describe('#asyncFromBlock', function () {
34 | it('should convert a block into a msgblock', function () {
35 | return asink(function * () {
36 | let block = new Block().fromHex(blockhex)
37 | let msgblock = yield new MsgBlock().asyncFromBlock(block)
38 | msgblock.isValid().should.equal(true)
39 | }, this)
40 | })
41 | })
42 |
43 | describe('@asyncFromBlock', function () {
44 | it('should convert a block into a msgblock', function () {
45 | return asink(function * () {
46 | let block = new Block().fromHex(blockhex)
47 | let msgblock = yield MsgBlock.asyncFromBlock(block)
48 | msgblock.isValid().should.equal(true)
49 | }, this)
50 | })
51 | })
52 |
53 | describe('#toBlock', function () {
54 | it('should convert a msgblock into a block', function () {
55 | let block = new Block().fromHex(blockhex)
56 | let msgblock = new MsgBlock().fromBlock(block)
57 | let block2 = msgblock.toBlock()
58 | block.toHex().should.equal(block2.toHex())
59 | })
60 | })
61 |
62 | describe('#isValid', function () {
63 | it('should know this msgblock is or is not valid', function () {
64 | let block = new Block().fromHex(blockhex)
65 | let msgblock = new MsgBlock().fromBlock(block)
66 | msgblock.isValid().should.equal(true)
67 | msgblock.setCmd('blocko')
68 | msgblock.isValid().should.equal(false)
69 | })
70 | })
71 | })
72 |
--------------------------------------------------------------------------------
/test/msg-get-addr.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let MsgGetAddr = require('../lib/msg-get-addr')
4 | let should = require('chai').should()
5 |
6 | describe('MsgGetAddr', function () {
7 | it('should exist', function () {
8 | should.exist(MsgGetAddr)
9 | should.exist(new MsgGetAddr())
10 | })
11 |
12 | describe('#isValid', function () {
13 | it('should know this is a valid getaddr msg', function () {
14 | new MsgGetAddr().isValid().should.equal(true)
15 | })
16 | })
17 | })
18 |
--------------------------------------------------------------------------------
/test/msg-get-blocks.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let GetBlocks = require('../lib/get-blocks')
4 | let MsgGetBlocks = require('../lib/msg-get-blocks')
5 | let asink = require('asink')
6 | let should = require('chai').should()
7 |
8 | describe('MsgGetBlocks', function () {
9 | let hashBuf = new Buffer(32)
10 | hashBuf.fill(0)
11 | let hashes = [hashBuf]
12 | let getblocks = new GetBlocks().fromHashes(hashes)
13 |
14 | it('should exist', function () {
15 | should.exist(MsgGetBlocks)
16 | should.exist(new MsgGetBlocks())
17 | })
18 |
19 | describe('#fromGetBlocks', function () {
20 | it('should convert from getblocks', function () {
21 | let msggetblocks = new MsgGetBlocks().fromGetBlocks(getblocks)
22 | msggetblocks.dataBuf.length.should.equal(4 + 1 + 0 + 32)
23 | })
24 | })
25 |
26 | describe('@fromGetBlocks', function () {
27 | it('should convert from getblocks', function () {
28 | let msggetblocks = MsgGetBlocks.fromGetBlocks(getblocks)
29 | msggetblocks.dataBuf.length.should.equal(4 + 1 + 0 + 32)
30 | })
31 | })
32 |
33 | describe('#asyncFromGetBlocks', function () {
34 | it('should convert from getblocks', function () {
35 | return asink(function * () {
36 | let msggetblocks = yield new MsgGetBlocks().asyncFromGetBlocks(getblocks)
37 | msggetblocks.dataBuf.length.should.equal(4 + 1 + 0 + 32)
38 | }, this)
39 | })
40 | })
41 |
42 | describe('@asyncFromGetBlocks', function () {
43 | it('should convert from getblocks', function () {
44 | return asink(function * () {
45 | let msggetblocks = yield MsgGetBlocks.asyncFromGetBlocks(getblocks)
46 | msggetblocks.dataBuf.length.should.equal(4 + 1 + 0 + 32)
47 | }, this)
48 | })
49 | })
50 |
51 | describe('#fromHashes', function () {
52 | it('should convert from hashes', function () {
53 | let msggetblocks = new MsgGetBlocks().fromHashes(hashes)
54 | msggetblocks.dataBuf.length.should.equal(4 + 1 + 0 + 32)
55 | })
56 | })
57 |
58 | describe('@fromHashes', function () {
59 | it('should convert from hashes', function () {
60 | let msggetblocks = MsgGetBlocks.fromHashes(hashes)
61 | msggetblocks.dataBuf.length.should.equal(4 + 1 + 0 + 32)
62 | })
63 | })
64 |
65 | describe('#asyncFromHashes', function () {
66 | it('should convert from hashes', function () {
67 | return asink(function * () {
68 | let msggetblocks = yield new MsgGetBlocks().asyncFromHashes(hashes)
69 | msggetblocks.dataBuf.length.should.equal(4 + 1 + 0 + 32)
70 | }, this)
71 | })
72 | })
73 |
74 | describe('@asyncFromHashes', function () {
75 | it('should convert from hashes', function () {
76 | return asink(function * () {
77 | let msggetblocks = yield MsgGetBlocks.asyncFromHashes(hashes)
78 | msggetblocks.dataBuf.length.should.equal(4 + 1 + 0 + 32)
79 | }, this)
80 | })
81 | })
82 |
83 | describe('#toGetBlocks', function () {
84 | it('should return getblocks', function () {
85 | let msggetblocks = new MsgGetBlocks().fromHashes(hashes)
86 | let getblocks2 = msggetblocks.toGetBlocks()
87 | getblocks2.toHex().should.equal(getblocks2.toHex())
88 | })
89 | })
90 |
91 | describe('#toHashes', function () {
92 | it('should return getblocks', function () {
93 | let msggetblocks = new MsgGetBlocks().fromHashes(hashes)
94 | let hashes2 = msggetblocks.toHashes()
95 | hashes2.length.should.equal(1)
96 | })
97 | })
98 |
99 | describe('#isValid', function () {
100 | it('should know this is a valid getblocks msg', function () {
101 | let msggetblocks = new MsgGetBlocks().fromHashes(hashes)
102 | msggetblocks.isValid().should.equal(true)
103 | })
104 | })
105 | })
106 |
--------------------------------------------------------------------------------
/test/msg-get-data.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let Inv = require('../lib/inv')
4 | let MsgGetData = require('../lib/msg-get-data')
5 | let should = require('chai').should()
6 |
7 | describe('MsgGetData', function () {
8 | it('should exist', function () {
9 | should.exist(MsgGetData)
10 | should.exist(new MsgGetData())
11 | })
12 |
13 | describe('#fromInvs', function () {
14 | it('should convert from invs', function () {
15 | let inv = new Inv().fromBuffer(new Buffer('01000000' + '0'.repeat(64), 'hex'))
16 | let msginv = new MsgGetData().fromInvs([inv])
17 | msginv.getCmd().should.equal('getdata')
18 | msginv.dataBuf.length.should.equal(1 + 4 + 32)
19 | })
20 | })
21 |
22 | describe('#toInvs', function () {
23 | it('should convert to invs', function () {
24 | let inv = new Inv().fromBuffer(new Buffer('01000000' + '0'.repeat(64), 'hex'))
25 | let msginv = new MsgGetData().fromInvs([inv])
26 | let invs2 = msginv.toInvs()
27 | invs2.length.should.equal(1)
28 | ;(invs2[0] instanceof Inv).should.equal(true)
29 | })
30 | })
31 |
32 | describe('#isValid', function () {
33 | it('should know this is a valid msg invs', function () {
34 | let inv = new Inv().fromBuffer(new Buffer('01000000' + '0'.repeat(64), 'hex'))
35 | let msginv = new MsgGetData().fromInvs([inv])
36 | msginv.isValid().should.equal(true)
37 | })
38 | })
39 | })
40 |
--------------------------------------------------------------------------------
/test/msg-get-headers.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let GetBlocks = require('../lib/get-blocks')
4 | let MsgGetHeaders = require('../lib/msg-get-headers')
5 | let asink = require('asink')
6 | let should = require('chai').should()
7 |
8 | describe('MsgGetHeaders', function () {
9 | let hashBuf = new Buffer(32)
10 | hashBuf.fill(0)
11 | let hashes = [hashBuf]
12 | let getblocks = new GetBlocks().fromHashes(hashes)
13 |
14 | it('should exist', function () {
15 | should.exist(MsgGetHeaders)
16 | should.exist(new MsgGetHeaders())
17 | })
18 |
19 | describe('#fromGetBlocks', function () {
20 | it('should convert from getblocks', function () {
21 | let msggetblocks = new MsgGetHeaders().fromGetBlocks(getblocks)
22 | msggetblocks.dataBuf.length.should.equal(4 + 1 + 0 + 32)
23 | })
24 | })
25 |
26 | describe('#asyncFromGetBlocks', function () {
27 | it('should convert from getblocks', function () {
28 | return asink(function * () {
29 | let msggetblocks = yield new MsgGetHeaders().asyncFromGetBlocks(getblocks)
30 | msggetblocks.dataBuf.length.should.equal(4 + 1 + 0 + 32)
31 | }, this)
32 | })
33 | })
34 |
35 | describe('#fromHashes', function () {
36 | it('should convert from hashes', function () {
37 | let msggetblocks = new MsgGetHeaders().fromHashes(hashes)
38 | msggetblocks.dataBuf.length.should.equal(4 + 1 + 0 + 32)
39 | })
40 | })
41 |
42 | describe('#asyncFromHashes', function () {
43 | it('should convert from hashes', function () {
44 | return asink(function * () {
45 | let msggetblocks = yield new MsgGetHeaders().asyncFromHashes(hashes)
46 | msggetblocks.dataBuf.length.should.equal(4 + 1 + 0 + 32)
47 | }, this)
48 | })
49 | })
50 |
51 | describe('#toGetBlocks', function () {
52 | it('should return getblocks', function () {
53 | let msggetblocks = new MsgGetHeaders().fromHashes(hashes)
54 | let getblocks2 = msggetblocks.toGetBlocks()
55 | getblocks2.toHex().should.equal(getblocks2.toHex())
56 | })
57 | })
58 |
59 | describe('#toHashes', function () {
60 | it('should return getblocks', function () {
61 | let msggetblocks = new MsgGetHeaders().fromHashes(hashes)
62 | let hashes2 = msggetblocks.toHashes()
63 | hashes2.length.should.equal(1)
64 | })
65 | })
66 |
67 | describe('#isValid', function () {
68 | it('should know this is a valid getheaders msg', function () {
69 | let msggetblocks = new MsgGetHeaders().fromHashes(hashes)
70 | msggetblocks.getCmd().should.equal('getheaders')
71 | msggetblocks.isValid().should.equal(true)
72 | })
73 | })
74 | })
75 |
--------------------------------------------------------------------------------
/test/msg-headers.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let Block = require('../lib/block')
4 | let BlockHeader = require('../lib/block-header')
5 | let MsgHeaders = require('../lib/msg-headers')
6 | let asink = require('asink')
7 | let should = require('chai').should()
8 |
9 | describe('MsgHeaders', function () {
10 | let blockhex = 'f9beb4d93200000001000000050505050505050505050505050505050505050505050505050505050505050509090909090909090909090909090909090909090909090909090909090909090200000003000000040000000101000000029e8d016a7b0dc49a325922d05da1f916d1e4d4f0cb840c9727f3d22ce8d1363f000000008c493046022100e9318720bee5425378b4763b0427158b1051eec8b08442ce3fbfbf7b30202a44022100d4172239ebd701dae2fbaaccd9f038e7ca166707333427e3fb2a2865b19a7f27014104510c67f46d2cbb29476d1f0b794be4cb549ea59ab9cc1e731969a7bf5be95f7ad5e7f904e5ccf50a9dc1714df00fbeb794aa27aaff33260c1032d931a75c56f2ffffffffa3195e7a1ab665473ff717814f6881485dc8759bebe97e31c301ffe7933a656f020000008b48304502201c282f35f3e02a1f32d2089265ad4b561f07ea3c288169dedcf2f785e6065efa022100e8db18aadacb382eed13ee04708f00ba0a9c40e3b21cf91da8859d0f7d99e0c50141042b409e1ebbb43875be5edde9c452c82c01e3903d38fa4fd89f3887a52cb8aea9dc8aec7e2c9d5b3609c03eb16259a2537135a1bf0f9c5fbbcbdbaf83ba402442ffffffff02206b1000000000001976a91420bb5c3bfaef0231dc05190e7f1c8e22e098991e88acf0ca0100000000001976a9149e3e2d23973a04ec1b02be97c30ab9f2f27c3b2c88ac00000000'
11 | let block = new Block().fromHex(blockhex)
12 | let blockHeader = block.blockHeader
13 |
14 | it('should exist', function () {
15 | should.exist(MsgHeaders)
16 | should.exist(new MsgHeaders())
17 | })
18 |
19 | describe('#fromBlockHeaders', function () {
20 | it('should make a msg from blockHeaders', function () {
21 | let msgheaders = new MsgHeaders().fromBlockHeaders([blockHeader])
22 | msgheaders.dataBuf.length.should.greaterThan(0)
23 | })
24 | })
25 |
26 | describe('@fromBlockHeaders', function () {
27 | it('should make a msg from blockHeaders', function () {
28 | let msgheaders = new MsgHeaders().fromBlockHeaders([blockHeader])
29 | msgheaders.dataBuf.length.should.greaterThan(0)
30 | })
31 | })
32 |
33 | describe('#asyncFromBlockHeaders', function () {
34 | it('should make a msg from blockHeaders', function () {
35 | return asink(function * () {
36 | let msgheaders = yield new MsgHeaders().asyncFromBlockHeaders([blockHeader])
37 | msgheaders.dataBuf.length.should.greaterThan(0)
38 | }, this)
39 | })
40 | })
41 |
42 | describe('#toBlockHeaders', function () {
43 | it('should make a msg from blockHeaders', function () {
44 | let msgheaders = new MsgHeaders().fromBlockHeaders([blockHeader, blockHeader, blockHeader])
45 | let blockHeaders = msgheaders.toBlockHeaders()
46 | blockHeaders.length.should.equal(3)
47 | ;(blockHeaders[0] instanceof BlockHeader).should.equal(true)
48 | })
49 | })
50 | })
51 |
--------------------------------------------------------------------------------
/test/msg-inv.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let Inv = require('../lib/inv')
4 | let MsgInv = require('../lib/msg-inv')
5 | let asink = require('asink')
6 | let should = require('chai').should()
7 |
8 | describe('MsgInv', function () {
9 | it('should exist', function () {
10 | should.exist(MsgInv)
11 | should.exist(new MsgInv())
12 | })
13 |
14 | describe('#fromInvs', function () {
15 | it('should convert from invs', function () {
16 | let inv = new Inv().fromBuffer(new Buffer('01000000' + '0'.repeat(64), 'hex'))
17 | let msginv = new MsgInv().fromInvs([inv])
18 | msginv.getCmd().should.equal('inv')
19 | msginv.dataBuf.length.should.equal(1 + 4 + 32)
20 | })
21 | })
22 |
23 | describe('@fromInvs', function () {
24 | it('should convert from invs', function () {
25 | let inv = new Inv().fromBuffer(new Buffer('01000000' + '0'.repeat(64), 'hex'))
26 | let msginv = MsgInv.fromInvs([inv])
27 | msginv.getCmd().should.equal('inv')
28 | msginv.dataBuf.length.should.equal(1 + 4 + 32)
29 | })
30 | })
31 |
32 | describe('#asyncFromInvs', function () {
33 | it('should convert from invs', function () {
34 | return asink(function * () {
35 | let inv = new Inv().fromBuffer(new Buffer('01000000' + '0'.repeat(64), 'hex'))
36 | let msginv = yield new MsgInv().asyncFromInvs([inv])
37 | msginv.getCmd().should.equal('inv')
38 | msginv.dataBuf.length.should.equal(1 + 4 + 32)
39 | }, this)
40 | })
41 | })
42 |
43 | describe('@asyncFromInvs', function () {
44 | it('should convert from invs', function () {
45 | return asink(function * () {
46 | let inv = new Inv().fromBuffer(new Buffer('01000000' + '0'.repeat(64), 'hex'))
47 | let msginv = yield MsgInv.asyncFromInvs([inv])
48 | msginv.getCmd().should.equal('inv')
49 | msginv.dataBuf.length.should.equal(1 + 4 + 32)
50 | }, this)
51 | })
52 | })
53 |
54 | describe('#toInvs', function () {
55 | it('should convert to invs', function () {
56 | let inv = new Inv().fromBuffer(new Buffer('01000000' + '0'.repeat(64), 'hex'))
57 | let msginv = new MsgInv().fromInvs([inv])
58 | let invs2 = msginv.toInvs()
59 | invs2.length.should.equal(1)
60 | ;(invs2[0] instanceof Inv).should.equal(true)
61 | })
62 | })
63 |
64 | describe('#isValid', function () {
65 | it('should know this is a valid msg invs', function () {
66 | let inv = new Inv().fromBuffer(new Buffer('01000000' + '0'.repeat(64), 'hex'))
67 | let msginv = new MsgInv().fromInvs([inv])
68 | msginv.isValid().should.equal(true)
69 | })
70 | })
71 | })
72 |
--------------------------------------------------------------------------------
/test/msg-mem-pool.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let MsgMemPool = require('../lib/msg-mem-pool')
4 | let should = require('chai').should()
5 |
6 | describe('MsgMemPool', function () {
7 | it('should exist', function () {
8 | should.exist(MsgMemPool)
9 | should.exist(new MsgMemPool())
10 | })
11 |
12 | describe('#isValid', function () {
13 | it('should know this is a valid mempool msg', function () {
14 | new MsgMemPool().isValid().should.equal(true)
15 | })
16 | })
17 | })
18 |
--------------------------------------------------------------------------------
/test/msg-not-found.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let Inv = require('../lib/inv')
4 | let MsgNotFound = require('../lib/msg-not-found')
5 | let should = require('chai').should()
6 |
7 | describe('MsgNotFound', function () {
8 | it('should exist', function () {
9 | should.exist(MsgNotFound)
10 | should.exist(new MsgNotFound())
11 | })
12 |
13 | describe('#fromInvs', function () {
14 | it('should convert from invs', function () {
15 | let inv = new Inv().fromBuffer(new Buffer('01000000' + '0'.repeat(64), 'hex'))
16 | let msginv = new MsgNotFound().fromInvs([inv])
17 | msginv.getCmd().should.equal('notfound')
18 | msginv.dataBuf.length.should.equal(1 + 4 + 32)
19 | })
20 | })
21 |
22 | describe('#toInvs', function () {
23 | it('should convert to invs', function () {
24 | let inv = new Inv().fromBuffer(new Buffer('01000000' + '0'.repeat(64), 'hex'))
25 | let msginv = new MsgNotFound().fromInvs([inv])
26 | let invs2 = msginv.toInvs()
27 | invs2.length.should.equal(1)
28 | ;(invs2[0] instanceof Inv).should.equal(true)
29 | })
30 | })
31 |
32 | describe('#isValid', function () {
33 | it('should know this is a valid msg invs', function () {
34 | let inv = new Inv().fromBuffer(new Buffer('01000000' + '0'.repeat(64), 'hex'))
35 | let msginv = new MsgNotFound().fromInvs([inv])
36 | msginv.isValid().should.equal(true)
37 | })
38 | })
39 | })
40 |
--------------------------------------------------------------------------------
/test/msg-ping.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let MsgPing = require('../lib/msg-ping')
4 | let Random = require('../lib/random')
5 | let asink = require('asink')
6 | let should = require('chai').should()
7 |
8 | describe('MsgPing', function () {
9 | it('should satisfy this basic API', function () {
10 | let msgping = new MsgPing()
11 | should.exist(msgping)
12 | msgping = new MsgPing()
13 | should.exist(msgping)
14 | should.exist(MsgPing.Mainnet)
15 | should.exist(MsgPing.Testnet)
16 | })
17 |
18 | describe('#fromRandom', function () {
19 | it('should find a msgping from random', function () {
20 | let msgping = new MsgPing().fromRandom()
21 | msgping.getCmd().should.equal('ping')
22 | msgping.dataBuf.length.should.equal(8)
23 | })
24 | })
25 |
26 | describe('@fromRandom', function () {
27 | it('should find a msgping from random', function () {
28 | let msgping = MsgPing.fromRandom()
29 | msgping.getCmd().should.equal('ping')
30 | msgping.dataBuf.length.should.equal(8)
31 | })
32 | })
33 |
34 | describe('#asyncFromRandom', function () {
35 | it('should find a msgping from random', function () {
36 | return asink(function * () {
37 | let msgping = yield new MsgPing().asyncFromRandom()
38 | msgping.getCmd().should.equal('ping')
39 | msgping.dataBuf.length.should.equal(8)
40 | }, this)
41 | })
42 | })
43 |
44 | describe('@asyncFromRandom', function () {
45 | it('should find a msgping from random', function () {
46 | return asink(function * () {
47 | let msgping = yield MsgPing.asyncFromRandom()
48 | msgping.getCmd().should.equal('ping')
49 | msgping.dataBuf.length.should.equal(8)
50 | }, this)
51 | })
52 | })
53 |
54 | describe('#isValid', function () {
55 | it('should know this is a valid ping', function () {
56 | let msgping = new MsgPing().fromRandom()
57 | msgping.isValid().should.equal(true)
58 | })
59 |
60 | it('should know this is an invalid ping', function () {
61 | let msgping = new MsgPing().fromRandom()
62 | msgping.setCmd('pingo')
63 | msgping.isValid().should.equal(false)
64 | })
65 |
66 | it('should know this is an invalid ping', function () {
67 | let msgping = new MsgPing().fromRandom()
68 | msgping.setData(Random.getRandomBuffer(9))
69 | msgping.isValid().should.equal(false)
70 | })
71 | })
72 | })
73 |
--------------------------------------------------------------------------------
/test/msg-pong.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let MsgPing = require('../lib/msg-ping')
4 | let MsgPong = require('../lib/msg-pong')
5 | let Random = require('../lib/random')
6 | let should = require('chai').should()
7 |
8 | describe('MsgPong', function () {
9 | it('should satisfy this basic API', function () {
10 | let msgping = new MsgPong()
11 | should.exist(msgping)
12 | msgping = new MsgPong()
13 | should.exist(msgping)
14 | should.exist(MsgPong.Mainnet)
15 | should.exist(MsgPong.Testnet)
16 | })
17 |
18 | describe('#fromMsgPing', function () {
19 | it('should find a msgpong from a msgping', function () {
20 | let msgping = new MsgPing().fromRandom()
21 | let msgpong = new MsgPong().fromMsgPing(msgping)
22 | Buffer.compare(msgping.dataBuf, msgpong.dataBuf).should.equal(0)
23 | msgpong.getCmd().should.equal('pong')
24 | })
25 | })
26 |
27 | describe('@fromMsgPing', function () {
28 | it('should find a msgpong from a msgping', function () {
29 | let msgping = MsgPing.fromRandom()
30 | let msgpong = MsgPong.fromMsgPing(msgping)
31 | Buffer.compare(msgping.dataBuf, msgpong.dataBuf).should.equal(0)
32 | msgpong.getCmd().should.equal('pong')
33 | })
34 | })
35 |
36 | describe('#isValid', function () {
37 | it('should know this is a valid pong', function () {
38 | let msgping = new MsgPing().fromRandom()
39 | let msgpong = new MsgPong().fromMsgPing(msgping)
40 | msgpong.isValid().should.equal(true)
41 | })
42 |
43 | it('should know this is an invalid ping', function () {
44 | let msgping = new MsgPing().fromRandom()
45 | let msgpong = new MsgPong().fromMsgPing(msgping)
46 | msgpong.setCmd('pongo')
47 | msgpong.isValid().should.equal(false)
48 | })
49 |
50 | it('should know this is an invalid ping', function () {
51 | let msgping = new MsgPing().fromRandom()
52 | let msgpong = new MsgPong().fromMsgPing(msgping)
53 | msgpong.setData(Random.getRandomBuffer(9))
54 | msgpong.isValid().should.equal(false)
55 | })
56 | })
57 | })
58 |
--------------------------------------------------------------------------------
/test/msg-reject.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let Reject = require('../lib/reject')
4 | let MsgReject = require('../lib/msg-reject')
5 | let VarInt = require('../lib/var-int')
6 | let asink = require('asink')
7 | let should = require('chai').should()
8 |
9 | describe('MsgReject', function () {
10 | it('should exist', function () {
11 | should.exist(MsgReject)
12 | should.exist(new MsgReject())
13 | })
14 |
15 | describe('#fromReject', function () {
16 | it('should convert from a reject', function () {
17 | let reject = new Reject().fromObject({
18 | typeVi: new VarInt().fromNumber(2),
19 | typeStr: 'tx',
20 | codeNum: 1,
21 | reasonVi: new VarInt().fromNumber(2),
22 | reasonStr: 'hi',
23 | extraBuf: new Buffer(0)
24 | })
25 | let msgreject = new MsgReject().fromReject(reject)
26 | Buffer.compare(msgreject.dataBuf, reject.toBuffer()).should.equal(0)
27 | })
28 | })
29 |
30 | describe('@fromReject', function () {
31 | it('should convert from a reject', function () {
32 | let reject = new Reject().fromObject({
33 | typeVi: new VarInt().fromNumber(2),
34 | typeStr: 'tx',
35 | codeNum: 1,
36 | reasonVi: new VarInt().fromNumber(2),
37 | reasonStr: 'hi',
38 | extraBuf: new Buffer(0)
39 | })
40 | let msgreject = MsgReject.fromReject(reject)
41 | Buffer.compare(msgreject.dataBuf, reject.toBuffer()).should.equal(0)
42 | })
43 | })
44 |
45 | describe('#asyncFromReject', function () {
46 | it('should convert from a reject', function () {
47 | return asink(function * () {
48 | let reject = new Reject().fromObject({
49 | typeVi: new VarInt().fromNumber(2),
50 | typeStr: 'tx',
51 | codeNum: 1,
52 | reasonVi: new VarInt().fromNumber(2),
53 | reasonStr: 'hi',
54 | extraBuf: new Buffer(0)
55 | })
56 | let msgreject = yield new MsgReject().asyncFromReject(reject)
57 | Buffer.compare(msgreject.dataBuf, reject.toBuffer()).should.equal(0)
58 | }, this)
59 | })
60 | })
61 |
62 | describe('@asyncFromReject', function () {
63 | it('should convert from a reject', function () {
64 | return asink(function * () {
65 | let reject = new Reject().fromObject({
66 | typeVi: new VarInt().fromNumber(2),
67 | typeStr: 'tx',
68 | codeNum: 1,
69 | reasonVi: new VarInt().fromNumber(2),
70 | reasonStr: 'hi',
71 | extraBuf: new Buffer(0)
72 | })
73 | let msgreject = yield MsgReject.asyncFromReject(reject)
74 | Buffer.compare(msgreject.dataBuf, reject.toBuffer()).should.equal(0)
75 | }, this)
76 | })
77 | })
78 |
79 | describe('#toReject', function () {
80 | it('should convert to a reject', function () {
81 | return asink(function * () {
82 | let reject = new Reject().fromObject({
83 | typeVi: new VarInt().fromNumber(2),
84 | typeStr: 'tx',
85 | codeNum: 1,
86 | reasonVi: new VarInt().fromNumber(2),
87 | reasonStr: 'hi',
88 | extraBuf: new Buffer(0)
89 | })
90 | let reject2 = new MsgReject().fromReject(reject).toReject()
91 | Buffer.compare(reject2.toBuffer(), reject.toBuffer()).should.equal(0)
92 | }, this)
93 | })
94 | })
95 |
96 | describe('#isValid', function () {
97 | it('should know this is a valid msgreject', function () {
98 | let reject = new Reject().fromObject({
99 | typeVi: new VarInt().fromNumber(2),
100 | typeStr: 'tx',
101 | codeNum: 1,
102 | reasonVi: new VarInt().fromNumber(2),
103 | reasonStr: 'hi',
104 | extraBuf: new Buffer(0)
105 | })
106 | let msgreject = new MsgReject().fromReject(reject)
107 | msgreject.isValid().should.equal(true)
108 | })
109 | })
110 | })
111 |
--------------------------------------------------------------------------------
/test/msg-send-header.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let MsgSendHeaders = require('../lib/msg-send-headers')
4 | let should = require('chai').should()
5 |
6 | describe('MsgSendHeaders', function () {
7 | it('should exist', function () {
8 | should.exist(MsgSendHeaders)
9 | should.exist(new MsgSendHeaders())
10 | })
11 |
12 | describe('#isValid', function () {
13 | it('should know this is a valid sendheaders msg', function () {
14 | new MsgSendHeaders().isValid().should.equal(true)
15 | })
16 | })
17 | })
18 |
--------------------------------------------------------------------------------
/test/msg-tx.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let Tx = require('../lib/tx')
4 | let MsgTx = require('../lib/msg-tx')
5 | let asink = require('asink')
6 | let should = require('chai').should()
7 |
8 | describe('MsgTx', function () {
9 | let txhex = '01000000029e8d016a7b0dc49a325922d05da1f916d1e4d4f0cb840c9727f3d22ce8d1363f000000008c493046022100e9318720bee5425378b4763b0427158b1051eec8b08442ce3fbfbf7b30202a44022100d4172239ebd701dae2fbaaccd9f038e7ca166707333427e3fb2a2865b19a7f27014104510c67f46d2cbb29476d1f0b794be4cb549ea59ab9cc1e731969a7bf5be95f7ad5e7f904e5ccf50a9dc1714df00fbeb794aa27aaff33260c1032d931a75c56f2ffffffffa3195e7a1ab665473ff717814f6881485dc8759bebe97e31c301ffe7933a656f020000008b48304502201c282f35f3e02a1f32d2089265ad4b561f07ea3c288169dedcf2f785e6065efa022100e8db18aadacb382eed13ee04708f00ba0a9c40e3b21cf91da8859d0f7d99e0c50141042b409e1ebbb43875be5edde9c452c82c01e3903d38fa4fd89f3887a52cb8aea9dc8aec7e2c9d5b3609c03eb16259a2537135a1bf0f9c5fbbcbdbaf83ba402442ffffffff02206b1000000000001976a91420bb5c3bfaef0231dc05190e7f1c8e22e098991e88acf0ca0100000000001976a9149e3e2d23973a04ec1b02be97c30ab9f2f27c3b2c88ac00000000'
10 |
11 | it('should exist', function () {
12 | let msgtx = new MsgTx()
13 | should.exist(MsgTx)
14 | should.exist(msgtx)
15 | })
16 |
17 | describe('#fromTx', function () {
18 | it('should convert a tx into a msgtx', function () {
19 | let tx = new Tx().fromHex(txhex)
20 | let msgtx = new MsgTx().fromTx(tx)
21 | msgtx.isValid().should.equal(true)
22 | })
23 | })
24 |
25 | describe('@fromTx', function () {
26 | it('should convert a tx into a msgtx', function () {
27 | let tx = new Tx().fromHex(txhex)
28 | let msgtx = MsgTx.fromTx(tx)
29 | msgtx.isValid().should.equal(true)
30 | })
31 | })
32 |
33 | describe('#asyncFromTx', function () {
34 | it('should convert a tx into a msgtx', function () {
35 | return asink(function * () {
36 | let tx = new Tx().fromHex(txhex)
37 | let msgtx = yield new MsgTx().asyncFromTx(tx)
38 | msgtx.isValid().should.equal(true)
39 | }, this)
40 | })
41 | })
42 |
43 | describe('@asyncFromTx', function () {
44 | it('should convert a tx into a msgtx', function () {
45 | return asink(function * () {
46 | let tx = new Tx().fromHex(txhex)
47 | let msgtx = yield MsgTx.asyncFromTx(tx)
48 | msgtx.isValid().should.equal(true)
49 | }, this)
50 | })
51 | })
52 |
53 | describe('#toTx', function () {
54 | it('should convert a msgtx into a tx', function () {
55 | let tx = new Tx().fromHex(txhex)
56 | let msgtx = new MsgTx().fromTx(tx)
57 | let tx2 = msgtx.toTx()
58 | tx.toHex().should.equal(tx2.toHex())
59 | })
60 | })
61 |
62 | describe('#isValid', function () {
63 | it('should know this msgtx is or is not valid', function () {
64 | let tx = new Tx().fromHex(txhex)
65 | let msgtx = new MsgTx().fromTx(tx)
66 | msgtx.isValid().should.equal(true)
67 | msgtx.setCmd('txo')
68 | msgtx.isValid().should.equal(false)
69 | })
70 | })
71 | })
72 |
--------------------------------------------------------------------------------
/test/msg-ver-ack.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let MsgVerAck = require('../lib/msg-ver-ack')
4 | let should = require('chai').should()
5 |
6 | describe('MsgVerAck', function () {
7 | it('should exist', function () {
8 | should.exist(MsgVerAck)
9 | should.exist(new MsgVerAck())
10 | })
11 |
12 | describe('#isValid', function () {
13 | it('should know this is a valid verack msg', function () {
14 | new MsgVerAck().isValid().should.equal(true)
15 | })
16 | })
17 | })
18 |
--------------------------------------------------------------------------------
/test/msg-version.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let Bn = require('../lib/bn')
4 | let MsgVersion = require('../lib/msg-version')
5 | let VarInt = require('../lib/var-int')
6 | let Version = require('../lib/version')
7 | let asink = require('asink')
8 | let should = require('chai').should()
9 |
10 | describe('Version', function () {
11 | let version = Version.fromObject({
12 | versionBytesNum: 0,
13 | servicesBuf: Buffer.alloc(8),
14 | timeBn: new Bn(0),
15 | addrRecvServicesBuf: Buffer.alloc(8),
16 | addrRecvIpAddrBuf: Buffer.alloc(16),
17 | addrRecvPort: 0,
18 | addrTransServicesBuf: Buffer.alloc(8),
19 | addrTransIpAddrBuf: Buffer.alloc(16),
20 | addrTransPort: 0,
21 | nonceBuf: Buffer.alloc(8),
22 | userAgentVi: VarInt.fromNumber('test'.length),
23 | userAgentBuf: new Buffer('test'),
24 | startHeightNum: 100,
25 | relay: true
26 | })
27 |
28 | it('should exist', function () {
29 | should.exist(Version)
30 | should.exist(new Version())
31 | })
32 |
33 | describe('#fromVersion', function () {
34 | it('should convert from a version', function () {
35 | let msgVersion = new MsgVersion().fromVersion(version)
36 | ;(msgVersion instanceof MsgVersion).should.equal(true)
37 | })
38 | })
39 |
40 | describe('@fromVersion', function () {
41 | it('should convert from a version', function () {
42 | let msgVersion = MsgVersion.fromVersion(version)
43 | ;(msgVersion instanceof MsgVersion).should.equal(true)
44 | })
45 | })
46 |
47 | describe('#asyncFromVersion', function () {
48 | it('should convert from a version', function () {
49 | return asink(function * () {
50 | let msgVersion = yield new MsgVersion().asyncFromVersion(version)
51 | ;(msgVersion instanceof MsgVersion).should.equal(true)
52 | }, this)
53 | })
54 | })
55 |
56 | describe('@asyncFromVersion', function () {
57 | it('should convert from a version', function () {
58 | return asink(function * () {
59 | let msgVersion = yield MsgVersion.asyncFromVersion(version)
60 | ;(msgVersion instanceof MsgVersion).should.equal(true)
61 | }, this)
62 | })
63 | })
64 |
65 | describe('#toVersion', function () {
66 | it('should get a version', function () {
67 | let msgVersion = MsgVersion.fromVersion(version)
68 | let version2 = msgVersion.toVersion()
69 | version2.toHex().should.equal(version.toHex())
70 | ;(version2 instanceof Version).should.equal(true)
71 | })
72 | })
73 |
74 | describe('#isValid', function () {
75 | it('should know this is a valid MsgVersion', function () {
76 | let msgVersion = MsgVersion.fromVersion(version)
77 | msgVersion.isValid().should.equal(true)
78 | })
79 | })
80 | })
81 |
--------------------------------------------------------------------------------
/test/op-code.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let should = require('chai').should()
4 | let OpCode = require('../lib/op-code')
5 |
6 | describe('OpCode', function () {
7 | it('should create a new OpCode', function () {
8 | let opCode = new OpCode(5)
9 | should.exist(opCode)
10 | })
11 |
12 | it('should have 121 opCodes', function () {
13 | let i = 0
14 | for (let key in OpCode) {
15 | if (key.indexOf('OP_') !== -1) {
16 | i++
17 | }
18 | }
19 | i.should.equal(121)
20 | })
21 |
22 | it('should convert to a string with this handy syntax', function () {
23 | new OpCode(0).toString().should.equal('OP_0')
24 | new OpCode(96).toString().should.equal('OP_16')
25 | new OpCode(97).toString().should.equal('OP_NOP')
26 | })
27 |
28 | it('should convert to a number with this handy syntax', function () {
29 | new OpCode().fromString('OP_0').toNumber().should.equal(0)
30 | new OpCode().fromString('OP_16').toNumber().should.equal(96)
31 | new OpCode().fromString('OP_NOP').toNumber().should.equal(97)
32 | })
33 |
34 | describe('#fromNumber', function () {
35 | it('should work for 0', function () {
36 | new OpCode().fromNumber(0).num.should.equal(0)
37 | })
38 | })
39 |
40 | describe('#toNumber', function () {
41 | it('should work for 0', function () {
42 | new OpCode().fromNumber(0).toNumber().should.equal(0)
43 | })
44 | })
45 |
46 | describe('#fromString', function () {
47 | it('should work for OP_0', function () {
48 | new OpCode().fromString('OP_0').num.should.equal(0)
49 | })
50 | })
51 |
52 | describe('#toString', function () {
53 | it('should work for OP_0', function () {
54 | new OpCode().fromString('OP_0').toString().should.equal('OP_0')
55 | })
56 | })
57 |
58 | describe('@str', function () {
59 | it('should exist and have op 185', function () {
60 | should.exist(OpCode.str)
61 | OpCode.str[185].should.equal('OP_NOP10')
62 | })
63 | })
64 | })
65 |
--------------------------------------------------------------------------------
/test/random.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | require('chai').should()
4 | let Random = require('../lib/random')
5 |
6 | describe('Random', function () {
7 | describe('@getRandomBuffer', function () {
8 | it('should return a buffer', function () {
9 | let bytes = Random.getRandomBuffer(8)
10 | bytes.length.should.equal(8)
11 | Buffer.isBuffer(bytes).should.equal(true)
12 | })
13 |
14 | it('should not equate two 256 bit random buffers', function () {
15 | let bytes1 = Random.getRandomBuffer(32)
16 | let bytes2 = Random.getRandomBuffer(32)
17 | bytes1.toString('hex').should.not.equal(bytes2.toString('hex'))
18 | })
19 |
20 | it('should generate 100 8 byte buffers in a row that are not equal', function () {
21 | let hexs = []
22 | for (let i = 0; i < 100; i++) {
23 | hexs[i] = Random.getRandomBuffer(8).toString('hex')
24 | }
25 | for (let i = 0; i < 100; i++) {
26 | for (let j = i + 1; j < 100; j++) {
27 | hexs[i].should.not.equal(hexs[j])
28 | }
29 | }
30 | })
31 | })
32 | })
33 |
--------------------------------------------------------------------------------
/test/reject.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let Reject = require('../lib/reject')
4 | let VarInt = require('../lib/var-int')
5 | let should = require('chai').should()
6 |
7 | describe('Reject', function () {
8 | it('should exist', function () {
9 | should.exist(Reject)
10 | should.exist(new Reject())
11 | })
12 |
13 | describe('#toBuffer', function () {
14 | it('should convert to a buffer', function () {
15 | let reject = new Reject().fromObject({
16 | typeVi: new VarInt().fromNumber(2),
17 | typeStr: 'tx',
18 | codeNum: 1,
19 | reasonVi: new VarInt().fromNumber(2),
20 | reasonStr: 'hi',
21 | extraBuf: new Buffer(0)
22 | })
23 | Buffer.isBuffer(reject.toBuffer()).should.equal(true)
24 | })
25 | })
26 |
27 | describe('#fromBuffer', function () {
28 | it('should convert from a buffer', function () {
29 | let reject = new Reject().fromObject({
30 | typeVi: new VarInt().fromNumber(2),
31 | typeStr: 'tx',
32 | codeNum: 1,
33 | reasonVi: new VarInt().fromNumber(2),
34 | reasonStr: 'hi',
35 | extraBuf: new Buffer(0)
36 | })
37 | let reject2 = new Reject().fromBuffer(reject.toBuffer())
38 | reject.typeStr.should.equal(reject2.typeStr)
39 | reject.codeNum.should.equal(reject2.codeNum)
40 | reject.reasonStr.should.equal(reject2.reasonStr)
41 | Buffer.compare(reject.extraBuf, reject2.extraBuf).should.equal(0)
42 | })
43 | })
44 | })
45 |
--------------------------------------------------------------------------------
/test/tx-out-map.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let should = require('chai').should()
4 | let TxOutMap = require('../lib/tx-out-map')
5 | let Tx = require('../lib/tx')
6 | let TxOut = require('../lib/tx-out')
7 | let Script = require('../lib/script')
8 | let Bn = require('../lib/bn')
9 |
10 | describe('TxOutMap', function () {
11 | let txHashBuf = new Buffer(32)
12 | txHashBuf.fill(0)
13 | let label = txHashBuf.toString('hex') + ':' + '0'
14 | let txOut = TxOut.fromProperties(new Bn(0), new Script('OP_RETURN'))
15 | let map = new Map()
16 | map.set(label, txOut)
17 | let tx = new Tx().fromHex('0100000001795b88d47a74e3be0948fc9d1b4737f96097474d57151afa6f77c787961e47cc120000006a47304402202289f9e1ae2ed981cd0bf62f822f6ae4aea40c65c7339d90643cea90de93ad1502205c8a08b3265f9ba7e99057d030d5b91c889a1b99f94a3a5b79d7daaada2409b6012103798b51f980e7a3690af6b43ce3467db75bede190385702c4d9d48c0a735ff4a9ffffffff01c0a83200000000001976a91447b8e62e008f82d95d1f565055a8243cc243d32388ac00000000')
18 |
19 | it('should make a new txOutMap', function () {
20 | let txOutMap = new TxOutMap()
21 | txOutMap = new TxOutMap({map: map})
22 | should.exist(txOutMap)
23 | should.exist(txOutMap.map)
24 | })
25 |
26 | describe('#fromObject', function () {
27 | it('should set a map', function () {
28 | let txOutMap = new TxOutMap().fromObject({map: map})
29 | txOutMap.map.get(label).toHex().should.equal(txOut.toHex())
30 | txOutMap.fromObject({})
31 | txOutMap.map.get(label).toHex().should.equal(txOut.toHex())
32 | })
33 | })
34 |
35 | describe('#toJSON', function () {
36 | it('convert to json', function () {
37 | let txOutMap = new TxOutMap().add(txHashBuf, 0, txOut)
38 | .add(txHashBuf, 1, txOut)
39 | .add(txHashBuf, 2, txOut)
40 | let json = txOutMap.toJSON()
41 | Object.keys(json).length.should.equal(3)
42 | })
43 | })
44 |
45 | describe('#fromJSON', function () {
46 | it('convert to/from json roundtrip', function () {
47 | let txOutMap = new TxOutMap().add(txHashBuf, 0, txOut)
48 | .add(txHashBuf, 1, txOut)
49 | .add(txHashBuf, 2, txOut)
50 | let txOutMap2 = new TxOutMap().fromJSON(txOutMap.toJSON())
51 | txOutMap2.get(txHashBuf, 0).toHex().should.equal(txOutMap.get(txHashBuf, 0).toHex())
52 | txOutMap2.get(txHashBuf, 1).toHex().should.equal(txOutMap.get(txHashBuf, 1).toHex())
53 | txOutMap2.get(txHashBuf, 2).toHex().should.equal(txOutMap.get(txHashBuf, 2).toHex())
54 | })
55 | })
56 |
57 | describe('#add', function () {
58 | it('should add a txOut to the txOutMap', function () {
59 | let txOutMap = new TxOutMap().add(txHashBuf, 0, txOut)
60 | should.exist(txOutMap.map.get(label))
61 | })
62 | })
63 |
64 | describe('#get', function () {
65 | it('should get a txOut', function () {
66 | let txOutMap = new TxOutMap().fromObject({map: map})
67 | txOutMap.get(txHashBuf, 0).toHex().should.equal(txOut.toHex())
68 | })
69 | })
70 |
71 | describe('#addTx', function () {
72 | it('should add all outputs from a tx', function () {
73 | let txOutMap = new TxOutMap().addTx(tx)
74 | let txHashBuf = tx.hash()
75 | let txOut = tx.txOuts[0]
76 | txOutMap.get(txHashBuf, 0).toHex().should.equal(txOut.toHex())
77 | })
78 | })
79 | })
80 |
--------------------------------------------------------------------------------
/test/tx-verifier-vectors-1.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let txInvalid = require('./vectors/bitcoind/tx_invalid')
4 | let txValid = require('./vectors/bitcoind/tx_valid')
5 | let testTxVerifierPartial = require('./helpers/tx-verifier').testTxVerifierPartial
6 |
7 | describe('TxVerifier Vectors 1/4', function () {
8 | testTxVerifierPartial(it, txValid, txInvalid, 0)
9 | })
10 |
--------------------------------------------------------------------------------
/test/tx-verifier-vectors-2.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let txInvalid = require('./vectors/bitcoind/tx_invalid')
4 | let txValid = require('./vectors/bitcoind/tx_valid')
5 | let testTxVerifierPartial = require('./helpers/tx-verifier').testTxVerifierPartial
6 |
7 | describe('TxVerifier Vectors 2/4', function () {
8 | testTxVerifierPartial(it, txValid, txInvalid, 1)
9 | })
10 |
--------------------------------------------------------------------------------
/test/tx-verifier-vectors-3.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let txInvalid = require('./vectors/bitcoind/tx_invalid')
4 | let txValid = require('./vectors/bitcoind/tx_valid')
5 | let testTxVerifierPartial = require('./helpers/tx-verifier').testTxVerifierPartial
6 |
7 | describe('TxVerifier Vectors 3/4', function () {
8 | testTxVerifierPartial(it, txValid, txInvalid, 2)
9 | })
10 |
--------------------------------------------------------------------------------
/test/tx-verifier-vectors-4.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let txInvalid = require('./vectors/bitcoind/tx_invalid')
4 | let txValid = require('./vectors/bitcoind/tx_valid')
5 | let testTxVerifierPartial = require('./helpers/tx-verifier').testTxVerifierPartial
6 |
7 | describe('TxVerifier Vectors 4/4', function () {
8 | testTxVerifierPartial(it, txValid, txInvalid, 3)
9 | })
10 |
--------------------------------------------------------------------------------
/test/var-int.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let Bn = require('../lib/bn')
4 | let should = require('chai').should()
5 | let Br = require('../lib/br')
6 | let Bw = require('../lib/bw')
7 | let VarInt = require('../lib/var-int')
8 |
9 | describe('VarInt', function () {
10 | it('should make a new varInt', function () {
11 | let buf = new Buffer('00', 'hex')
12 | let varInt = new VarInt(buf)
13 | should.exist(varInt)
14 | varInt.buf.toString('hex').should.equal('00')
15 | varInt = new VarInt(buf)
16 | should.exist(varInt)
17 | varInt.buf.toString('hex').should.equal('00')
18 |
19 | // varInts can have multiple buffer representations
20 | VarInt.fromNumber(0).toNumber().should.equal(new VarInt(new Buffer([0xFD, 0, 0])).toNumber())
21 | VarInt.fromNumber(0).toBuffer().toString('hex').should.not.equal(new VarInt().fromBuffer(new Buffer([0xFD, 0, 0])).toBuffer().toString('hex'))
22 | })
23 |
24 | describe('#fromObject', function () {
25 | it('should set a buffer', function () {
26 | let buf = new Buffer('00', 'hex')
27 | let varInt = new VarInt().fromObject({buf: buf})
28 | varInt.buf.toString('hex').should.equal('00')
29 | varInt.fromObject({})
30 | varInt.buf.toString('hex').should.equal('00')
31 | })
32 | })
33 |
34 | describe('#fromJSON', function () {
35 | it('should set a buffer', function () {
36 | let buf = new Bw().writeVarIntNum(5).toBuffer()
37 | let varInt = new VarInt().fromJSON(buf.toString('hex'))
38 | varInt.toNumber().should.equal(5)
39 | })
40 | })
41 |
42 | describe('#toJSON', function () {
43 | it('should return a buffer', function () {
44 | let buf = new Bw().writeVarIntNum(5).toBuffer()
45 | let varInt = new VarInt().fromJSON(buf.toString('hex'))
46 | varInt.toJSON().should.equal('05')
47 | })
48 | })
49 |
50 | describe('#fromBuffer', function () {
51 | it('should set a buffer', function () {
52 | let buf = new Bw().writeVarIntNum(5).toBuffer()
53 | let varInt = new VarInt().fromBuffer(buf)
54 | varInt.toNumber().should.equal(5)
55 | })
56 | })
57 |
58 | describe('#fromBr', function () {
59 | it('should set a buffer reader', function () {
60 | let buf = new Bw().writeVarIntNum(5).toBuffer()
61 | let br = new Br(buf)
62 | let varInt = new VarInt().fromBr(br)
63 | varInt.toNumber().should.equal(5)
64 | })
65 | })
66 |
67 | describe('#fromBn', function () {
68 | it('should set a number', function () {
69 | let varInt = new VarInt().fromBn(new Bn(5))
70 | varInt.toNumber().should.equal(5)
71 | })
72 | })
73 |
74 | describe('@fromBn', function () {
75 | it('should set a number', function () {
76 | let varInt = VarInt.fromBn(new Bn(5))
77 | varInt.toNumber().should.equal(5)
78 | })
79 | })
80 |
81 | describe('#fromNumber', function () {
82 | it('should set a number', function () {
83 | let varInt = new VarInt().fromNumber(5)
84 | varInt.toNumber().should.equal(5)
85 | })
86 | })
87 |
88 | describe('@fromNumber', function () {
89 | it('should set a number', function () {
90 | let varInt = VarInt.fromNumber(5)
91 | varInt.toNumber().should.equal(5)
92 | })
93 | })
94 |
95 | describe('#toBuffer', function () {
96 | it('should return a buffer', function () {
97 | let buf = new Bw().writeVarIntNum(5).toBuffer()
98 | let varInt = new VarInt(buf)
99 | varInt.toBuffer().toString('hex').should.equal(buf.toString('hex'))
100 | })
101 | })
102 |
103 | describe('#toBn', function () {
104 | it('should return a buffer', function () {
105 | let varInt = VarInt.fromNumber(5)
106 | varInt.toBn().toString().should.equal(new Bn(5).toString())
107 | })
108 | })
109 |
110 | describe('#toNumber', function () {
111 | it('should return a buffer', function () {
112 | let varInt = VarInt.fromNumber(5)
113 | varInt.toNumber().should.equal(5)
114 | })
115 | })
116 | })
117 |
--------------------------------------------------------------------------------
/test/vectors/coolest-tx-ever-sent.json:
--------------------------------------------------------------------------------
1 | {
2 | "tx": "0100000002bab3b61c5a7facd63a090addb0a4ea1863ccb0f8d6d8d5c1d7b747b5aa9b17bc01000000fdfe000048304502210089666e61b0486a71f2103414315aa4c418dc65815f8b8bfcfab1037c3c2a66210220428b8162874cfc97e05dee6f901dae03820d11011fa7828ecb8fbca45be2188d01493046022100c6c19d75b6d5c911813b2b64cee07c6338f54bca0395264e53c3b3d8ca8e4f8e022100bbcb8d32960e62f26e3e5bdeca605a8b49f1a42cedd20bad507a1bc23c565faf01ab522103c86390eb5230237f31de1f02e70ce61e77f6dbfefa7d0e4ed4f6b3f78f85d8ec2103193f28067b502b34cac9eae39f74dba4815e1278bab31516efb29bd8de2c1bea21032462c60ebc21f4d38b3c4ccb33be77b57ae72762be12887252db18fd6225befb53aeffffffffb1678d9af66c4b8cde45d0d445749322746ab900e546d3900cf30f436e73428a01000000fd470100483045022100a7af036203a1e6b2e833b0d6b402958d58f9ffaaff4969539f213634f17600ee0220192594a5c60f70e5a97dc48fec06df0d3b17c44850162d3d552c7d8653d159a001483045022072020e687ce937828827e85bc916716a9099a510e7fbd96a2836617afa370108022100ce737ad7b46c249cda2b09cb065ea16078b9a3a31f6fc6b63385f645abfdafdf01493046022100c30c5f6e943a78d502216e019821545b940b940784e83051945d89c92ec245f0022100b5c76266878ee8f29f65401fb0af6ba3941641740d846cb551059c0ad25b798c01ab532103c86390eb5230237f31de1f02e70ce61e77f6dbfefa7d0e4ed4f6b3f78f85d8ec2103193f28067b502b34cac9eae39f74dba4815e1278bab31516efb29bd8de2c1bea21032462c60ebc21f4d38b3c4ccb33be77b57ae72762be12887252db18fd6225befb53aeffffffff0150c300000000000017142c68bb496b123d39920fcfdc206daa08bbe58506b17500000000",
3 | "intx0": "010000000290c5e425bfba62bd5b294af0414d8fa3ed580c5ca6f351ccc23e360b14ff7f470100000091004730440220739d9ab2c3e7089e7bd311f267a65dc0ea00f49619cb61ec016a5038016ed71202201b88257809b623d471e429787c36e0a9bcd2a058fc0c75fd9c25f905657e3b9e01ab512103c86390eb5230237f31de1f02e70ce61e77f6dbfefa7d0e4ed4f6b3f78f85d8ec2103193f28067b502b34cac9eae39f74dba4815e1278bab31516efb29bd8de2c1bea52aeffffffffdd7f3ce640a2fb04dbe24630aa06e4299fbb1d3fe585fe4f80be4a96b5ff0a0d01000000b400483045022100a28d2ace2f1cb4b2a58d26a5f1a2cc15cdd4cf1c65cee8e4521971c7dc60021c0220476a5ad62bfa7c18f9174d9e5e29bc0062df543e2c336ae2c77507e462bbf95701ab512103c86390eb5230237f31de1f02e70ce61e77f6dbfefa7d0e4ed4f6b3f78f85d8ec2103193f28067b502b34cac9eae39f74dba4815e1278bab31516efb29bd8de2c1bea21032462c60ebc21f4d38b3c4ccb33be77b57ae72762be12887252db18fd6225befb53aeffffffff02e0fd1c00000000001976a9148501106ab5492387998252403d70857acfa1586488ac50c3000000000000171499050637f553f03cc0f82bbfe98dc99f10526311b17500000000",
4 | "intx1": "0100000001bab3b61c5a7facd63a090addb0a4ea1863ccb0f8d6d8d5c1d7b747b5aa9b17bc000000006b483045022056eaab9d21789a762c7aefdf84d90daf35f7d98bc917c83a1ae6fa24d44f2b94022100a8e1d45d4bc51ad3a192b1b9d582a4711971b0e957012a303950b83eda3d306c01210375228faaa97a02433f4f126ba8d5a295b92466608acf8d13740130d5bbf9cdb4ffffffff0240771b00000000001976a914bb05d829af3b31730e69b7eeb83c1c0d21d362eb88ac50c3000000000000171452cf84e83d1dc919ef4ada30c44cf4349ee55af9b17500000000"
5 | }
6 |
--------------------------------------------------------------------------------
/test/vectors/kdf.json:
--------------------------------------------------------------------------------
1 | {
2 | "PBKDF2": {
3 | "valid": [
4 | {
5 | "p": "70617373776f7264",
6 | "s": "73616c74",
7 | "c": 1,
8 | "dkLen": 20,
9 | "hmacf": "sha1",
10 | "key": "0c60c80f961f0e71f3a9b524af6012062fe037a6"
11 | },
12 | {
13 | "p": "70617373776f7264",
14 | "s": "73616c74",
15 | "c": 2,
16 | "dkLen": 20,
17 | "hmacf": "sha1",
18 | "key": "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957"
19 | },
20 | {
21 | "p": "70617373776f7264",
22 | "s": "73616c74",
23 | "c": 4096,
24 | "dkLen": 20,
25 | "hmacf": "sha1",
26 | "key": "4b007901b765489abead49d926f721d065a429c1"
27 | },
28 | {
29 | "p": "70617373776f726450415353574f524470617373776f7264",
30 | "s": "73616c7453414c5473616c7453414c5473616c7453414c5473616c7453414c5473616c74",
31 | "c": 4096,
32 | "dkLen": 25,
33 | "hmacf": "sha1",
34 | "key": "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038"
35 | },
36 | {
37 | "p": "7061737300776f7264",
38 | "s": "7361006c74",
39 | "c": 4096,
40 | "dkLen": 16,
41 | "hmacf": "sha1",
42 | "key": "56fa6aa75548099dcc37d7f03425e0c3"
43 | }
44 | ]
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/test/vectors/sig.json:
--------------------------------------------------------------------------------
1 | {
2 | "valid": [
3 | {
4 | "compact": {
5 | "hex": "1f33a69cd2065432a30f3d1ce4eb0d59b8ab58c74f27c41a7fdb5696ad4e6108c96f807982866f785d3f6418d24163ddae117b7db4d5fdf0071de069fa54342262",
6 | "compressed": true,
7 | "i": 0
8 | }
9 | },
10 | {
11 | "compact": {
12 | "hex": "1b54c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed07082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5",
13 | "compressed": false,
14 | "i": 0
15 | }
16 | },
17 | {
18 | "compact": {
19 | "hex": "1fff466a9f1b7b273e2f4c3ffe032eb2e814121ed18ef84665d0f515360dab3dd06fc95f5132e5ecfdc8e5e6e616cc77151455d46ed48f5589b7db7771a332b283",
20 | "compressed": true,
21 | "i": 0
22 | }
23 | },
24 | {
25 | "compact": {
26 | "hex": "1cc0dafec8251f1d5010289d210232220b03202cba34ec11fec58b3e93a85b91d375afdc06b7d6322a590955bf264e7aaa155847f614d80078a90292fe205064d3",
27 | "compressed": false,
28 | "i": 1
29 | }
30 | },
31 | {
32 | "compact": {
33 | "hex": "1f7186363571d65e084e7f02b0b77c3ec44fb1b257dee26274c38c928986fea45d0de0b38e06807e46bda1f1e293f4f6323e854c86d58abdd00c46c16441085df6",
34 | "compressed": true,
35 | "i": 0
36 | }
37 | },
38 | {
39 | "compact": {
40 | "hex": "1cfbfe5076a15860ba8ed00e75e9bd22e05d230f02a936b653eb55b61c99dda4870e68880ebb0050fe4312b1b1eb0899e1b82da89baa5b895f612619edf34cbd37",
41 | "compressed": false,
42 | "i": 1
43 | }
44 | },
45 | {
46 | "compact": {
47 | "hex": "20cde1302d83f8dd835d89aef803c74a119f561fbaef3eb9129e45f30de86abbf906ce643f5049ee1f27890467b77a6a8e11ec4661cc38cd8badf90115fbd03cef",
48 | "compressed": true,
49 | "i": 1
50 | }
51 | }
52 | ],
53 | "invalid": {
54 | "compact": [
55 | {
56 | "exception": "Invalid signature parameter",
57 | "hex": "23987ceade6a304fc5823ab38f99fc3c5f772a2d3e89ea05931e2726105fc53b9e601fc3231f35962c714fcbce5c95b427496edc7ae8b3d12e93791d7629795b62"
58 | },
59 | {
60 | "exception": "Invalid signature length",
61 | "hex": "1c987ceade6a304fc5823ab38f99fc3c5f772a2d3e89ea05931e2726105fc53b9e601fc3231f35962c714fcbce5c95b427496edc7ae8b3d12e93791d7629795b62000000"
62 | },
63 | {
64 | "exception": "Invalid signature length",
65 | "hex": "1c987ceade6a304fc5823ab38f99fc3c5f772a2d3e89ea05931e2726105fc53b9e601fc3231f35962c714fcbce5c95b427496edc7ae8b3d12e9379"
66 | }
67 | ]
68 | }
69 | }
70 |
71 |
--------------------------------------------------------------------------------
/test/vectors/sighash-single-bug.json:
--------------------------------------------------------------------------------
1 | {
2 | "tx": "01000000022f196cf1e5bd426a04f07b882c893b5b5edebad67da6eb50f066c372ed736d5f000000006a47304402201f81ac31b52cb4b1ceb83f97d18476f7339b74f4eecd1a32c251d4c3cccfffa402203c9143c18810ce072969e4132fdab91408816c96b423b2be38eec8a3582ade36012102aa5a2b334bd8f135f11bc5c477bf6307ff98ed52d3ed10f857d5c89adf5b02beffffffffff8755f073f1170c0d519457ffc4acaa7cb2988148163b5dc457fae0fe42aa19000000009200483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a530347304402206da827fb26e569eb740641f9c1a7121ee59141703cbe0f903a22cc7d9a7ec7ac02204729f989b5348b3669ab020b8c4af01acc4deaba7c0d9f8fa9e06b2106cbbfeb01ffffffff010000000000000000016a00000000",
3 | "intx0": "010000000143d4b858145e44fbd121dbc592ae931b459f9ec99418a83e8cb6d94330a80c24010000006b483045022100f85c9fceb6d4d38c82a9121acbf68ffffe784017b05554b586464fdbe473340d0220077780b2022c2d97752961c2cb03ed9202cbe57647510746c6bd31276c8a3c5201210314ffdda8717bc586284c05f37192990f774c391e2088516d2983094d3a33e7c3ffffffff02a0860100000000001976a91419660c27383b347112e92caba64fb1d07e9f63bf88ac40c33800000000001976a914825537afe6d73324f862027690651a64c688dfb788ac00000000",
4 | "intx1": "01000000017a2133643a513a004ff4d09bbcc7a05d7ee7d3a1d28889f0c06d06f9db1d1d8000000000fd4d0200473044022011cb94542051b8be5563b39da022d7531673ed4b53b6b3f8536794150f7d75e802205a6774c0630964457c2d4a087e5a23167155f661082746dc711ba348ca4d4187014d01025121033d1d799df4bbb828cb8fd9146407ec974948609031e50224b491a6291b77d76b21033d1d799df4bbb828cb8fd9146407ec974948609031e50224b491a6291b77d76b21033d1d799df4bbb828cb8fd9146407ec974948609031e50224b491a6291b77d76b21033d1d799df4bbb828cb8fd9146407ec974948609031e50224b491a6291b77d76b21033d1d799df4bbb828cb8fd9146407ec974948609031e50224b491a6291b77d76b21033d1d799df4bbb828cb8fd9146407ec974948609031e50224b491a6291b77d76b21033d1d799df4bbb828cb8fd9146407ec974948609031e50224b491a6291b77d76b21033d1d799df4bbb828cb8fd9146407ec974948609031e50224b491a6291b77d76b21033d1d799df4bbb828cb8fd9146407ec974948609031e50224b491a6291b77d76b21033d1d799df4bbb828cb8fd9146407ec974948609031e50224b491a6291b77d76b21033d1d799df4bbb828cb8fd9146407ec974948609031e50224b491a6291b77d76b21033d1d799df4bbb828cb8fd9146407ec974948609031e50224b491a6291b77d76b21033d1d799df4bbb828cb8fd9146407ec974948609031e50224b491a6291b77d76b21033d1d799df4bbb828cb8fd9146407ec974948609031e50224b491a6291b77d76b21033d1d799df4bbb828cb8fd9146407ec974948609031e50224b491a6291b77d76b5faeffffffff01a08601000000000091483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a53037552210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c7152ae00000000"
5 | }
6 |
--------------------------------------------------------------------------------
/test/version.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let Version = require('../lib/version')
4 | let Bn = require('../lib/bn')
5 | let should = require('chai').should()
6 | let VarInt = require('../lib/var-int')
7 |
8 | describe('Version', function () {
9 | it('should exist', function () {
10 | should.exist(Version)
11 | should.exist(new Version())
12 | })
13 |
14 | describe('#toBuffer', function () {
15 | it('should convert to buffer', function () {
16 | let version = Version.fromObject({
17 | versionBytesNum: 0,
18 | servicesBuf: Buffer.alloc(8),
19 | timeBn: new Bn(0),
20 | addrRecvServicesBuf: Buffer.alloc(8),
21 | addrRecvIpAddrBuf: Buffer.alloc(16),
22 | addrRecvPort: 0,
23 | addrTransServicesBuf: Buffer.alloc(8),
24 | addrTransIpAddrBuf: Buffer.alloc(16),
25 | addrTransPort: 0,
26 | nonceBuf: Buffer.alloc(8),
27 | userAgentVi: VarInt.fromNumber('test'.length),
28 | userAgentBuf: new Buffer('test'),
29 | startHeightNum: 100,
30 | relay: true
31 | })
32 | Buffer.isBuffer(version.toBuffer()).should.equal(true)
33 | })
34 | })
35 |
36 | describe('#fromBuffer', function () {
37 | it('should convert from buffer', function () {
38 | let version = Version.fromObject({
39 | versionBytesNum: 0,
40 | servicesBuf: Buffer.alloc(8),
41 | timeBn: new Bn(0),
42 | addrRecvServicesBuf: Buffer.alloc(8),
43 | addrRecvIpAddrBuf: Buffer.alloc(16),
44 | addrRecvPort: 0,
45 | addrTransServicesBuf: Buffer.alloc(8),
46 | addrTransIpAddrBuf: Buffer.alloc(16),
47 | addrTransPort: 0,
48 | nonceBuf: Buffer.alloc(8),
49 | userAgentVi: VarInt.fromNumber('test'.length),
50 | userAgentBuf: new Buffer('test'),
51 | startHeightNum: 100,
52 | relay: true
53 | })
54 | version = new Version().fromBuffer(version.toBuffer())
55 | ;(version instanceof Version).should.equal(true)
56 | })
57 | })
58 |
59 | describe('@fromBuffer', function () {
60 | it('should convert from buffer', function () {
61 | let version = Version.fromObject({
62 | versionBytesNum: 0,
63 | servicesBuf: Buffer.alloc(8),
64 | timeBn: new Bn(0),
65 | addrRecvServicesBuf: Buffer.alloc(8),
66 | addrRecvIpAddrBuf: Buffer.alloc(16),
67 | addrRecvPort: 0,
68 | addrTransServicesBuf: Buffer.alloc(8),
69 | addrTransIpAddrBuf: Buffer.alloc(16),
70 | addrTransPort: 0,
71 | nonceBuf: Buffer.alloc(8),
72 | userAgentVi: VarInt.fromNumber('test'.length),
73 | userAgentBuf: new Buffer('test'),
74 | startHeightNum: 100,
75 | relay: true
76 | })
77 | version = Version.fromBuffer(version.toBuffer())
78 | ;(version instanceof Version).should.equal(true)
79 | })
80 | })
81 | })
82 |
--------------------------------------------------------------------------------
/test/workers-result.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let WorkersResult = require('../lib/workers-result')
4 | let cmp = require('../lib/cmp')
5 | let should = require('chai').should()
6 |
7 | describe('WorkersResult', function () {
8 | it('should satisfy this basic API', function () {
9 | let workersResult = new WorkersResult()
10 | should.exist(workersResult)
11 | })
12 |
13 | describe('#fromResult', function () {
14 | it('should make a workersResult from a string', function () {
15 | let result = 'test result'
16 | let workersResult = new WorkersResult().fromResult(result, 0)
17 | cmp(workersResult.resbuf, new Buffer(JSON.stringify(result))).should.equal(true)
18 | workersResult.isError.should.equal(false)
19 | workersResult.id.should.equal(0)
20 | })
21 | })
22 |
23 | describe('@fromResult', function () {
24 | it('should make a workersResult from a string', function () {
25 | let result = 'test result'
26 | let workersResult = WorkersResult.fromResult(result, 0)
27 | cmp(workersResult.resbuf, new Buffer(JSON.stringify(result))).should.equal(true)
28 | workersResult.isError.should.equal(false)
29 | workersResult.id.should.equal(0)
30 | })
31 | })
32 |
33 | describe('#fromError', function () {
34 | it('should make a workersResult from an error', function () {
35 | let error = new Error('oh noes, error')
36 | let workersResult = new WorkersResult().fromError(error, 0)
37 | cmp(workersResult.resbuf, new Buffer(JSON.stringify(error.message))).should.equal(true)
38 | workersResult.isError.should.equal(true)
39 | workersResult.id.should.equal(0)
40 | })
41 | })
42 |
43 | describe('#toBuffer', function () {
44 | it('should make a buffer from a workersResult', function () {
45 | let result = 'test result'
46 | let workersResult = new WorkersResult().fromResult(result, 0)
47 | workersResult.toBuffer().length.should.greaterThan(0)
48 | })
49 |
50 | it('should make a buffer from a workersResult error', function () {
51 | let error = new Error('oh noes, error')
52 | let workersResult = new WorkersResult().fromError(error, 0)
53 | workersResult.toBuffer().length.should.greaterThan(0)
54 | })
55 | })
56 |
57 | describe('#fromBuffer', function () {
58 | it('should make a workersResult from a workersResult buffer', function () {
59 | let result = 'test result'
60 | let workersResult = new WorkersResult().fromResult(result, 0)
61 | let buf = workersResult.toBuffer()
62 | workersResult = new WorkersResult().fromBuffer(buf)
63 | cmp(workersResult.resbuf, new Buffer(JSON.stringify(result))).should.equal(true)
64 | })
65 |
66 | it('should make a workersResult error from a workersResult buffer', function () {
67 | let error = new Error('oh noes, error')
68 | let workersResult = new WorkersResult().fromError(error, 0)
69 | let buf = workersResult.toBuffer()
70 | workersResult = new WorkersResult().fromBuffer(buf)
71 | cmp(workersResult.resbuf, new Buffer(JSON.stringify(error.message))).should.equal(true)
72 | })
73 | })
74 | })
75 |
--------------------------------------------------------------------------------
/test/workers.js:
--------------------------------------------------------------------------------
1 | /* global describe,it */
2 | 'use strict'
3 | let Bip32 = require('../lib/bip-32')
4 | let Hash = require('../lib/hash')
5 | let PrivKey = require('../lib/priv-key')
6 | let PubKey = require('../lib/pub-key')
7 | let Workers = require('../lib/workers')
8 | let asink = require('asink')
9 | let should = require('chai').should()
10 |
11 | describe('Workers', function () {
12 | it('should satisfy this basic API', function () {
13 | let workers = new Workers()
14 | should.exist(workers.nativeWorkers)
15 | should.exist(workers)
16 | })
17 |
18 | describe('#asyncObjectMethod', function () {
19 | it('should compute this method in the workers', function () {
20 | return asink(function * () {
21 | let bip32 = new Bip32().fromRandom()
22 | let workersResult = yield Workers.asyncObjectMethod(bip32, 'toString', [])
23 | let str = JSON.parse(workersResult.resbuf.toString())
24 | str[0].should.equal('x')
25 | }, this)
26 | })
27 |
28 | it('should compute this method with Yours Bitcoin object in args in the workers', function () {
29 | return asink(function * () {
30 | let privKey = new PrivKey().fromRandom()
31 | let pubKey1 = new PubKey().fromPrivKey(privKey)
32 | let workersResult = yield Workers.asyncObjectMethod(new PubKey(), 'fromPrivKey', [privKey])
33 | let pubKey2 = new PubKey().fromFastBuffer(workersResult.resbuf)
34 | pubKey1.toString().should.equal(pubKey2.toString())
35 | }, this)
36 | })
37 | })
38 |
39 | describe('#asyncClassMethod', function () {
40 | it('should compute this method in the workers', function () {
41 | return asink(function * () {
42 | let buf = new Buffer([0, 1, 2, 3, 4])
43 | let args = [buf]
44 | let workersResult = yield Workers.asyncClassMethod('Hash', 'sha1', args)
45 | let hashBuf1 = workersResult.resbuf
46 | let hashBuf2 = Hash.sha1(buf)
47 | Buffer.compare(hashBuf1, hashBuf2).should.equal(0)
48 | }, this)
49 | })
50 | })
51 | })
52 |
--------------------------------------------------------------------------------