You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

229 lines
9.2 KiB

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const __1 = require("..");
const __2 = require("..");
const { describe, it, beforeEach } = require('mocha');
const assert = require('assert');
const proxyquire = require('proxyquire');
const hoodwink = require('hoodwink');
const tinysecp = require('tiny-secp256k1');
const fixtures = require('../ts_test/fixtures/ecpair.json');
const NETWORKS_LIST = []; // Object.values(NETWORKS)
for (const networkName in __2.networks) {
if (networkName)
NETWORKS_LIST.push(__2.networks[networkName]);
}
const ZERO = Buffer.alloc(32, 0);
const ONE = Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex');
const GROUP_ORDER = Buffer.from('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141', 'hex');
const GROUP_ORDER_LESS_1 = Buffer.from('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140', 'hex');
describe('ECPair', () => {
describe('getPublicKey', () => {
let keyPair;
beforeEach(() => {
keyPair = __1.ECPair.fromPrivateKey(ONE);
});
it('calls pointFromScalar lazily', hoodwink(() => {
// @ts-ignore
assert.strictEqual(keyPair.__Q, undefined);
// .publicKey forces the memoization
assert.strictEqual(keyPair.publicKey.toString('hex'), '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798');
assert.strictEqual(
// @ts-ignore
keyPair.__Q.toString('hex'), '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798');
}));
});
describe('fromPrivateKey', () => {
it('defaults to compressed', () => {
const keyPair = __1.ECPair.fromPrivateKey(ONE);
assert.strictEqual(keyPair.compressed, true);
});
it('supports the uncompressed option', () => {
const keyPair = __1.ECPair.fromPrivateKey(ONE, {
compressed: false,
});
assert.strictEqual(keyPair.compressed, false);
});
it('supports the network option', () => {
const keyPair = __1.ECPair.fromPrivateKey(ONE, {
compressed: false,
network: __2.networks.testnet,
});
assert.strictEqual(keyPair.network, __2.networks.testnet);
});
fixtures.valid.forEach(f => {
it('derives public key for ' + f.WIF, () => {
const d = Buffer.from(f.d, 'hex');
const keyPair = __1.ECPair.fromPrivateKey(d, {
compressed: f.compressed,
});
assert.strictEqual(keyPair.publicKey.toString('hex'), f.Q);
});
});
fixtures.invalid.fromPrivateKey.forEach(f => {
it('throws ' + f.exception, () => {
const d = Buffer.from(f.d, 'hex');
assert.throws(() => {
// @ts-ignore
__1.ECPair.fromPrivateKey(d, f.options);
}, new RegExp(f.exception));
});
});
});
describe('fromPublicKey', () => {
fixtures.invalid.fromPublicKey.forEach(f => {
it('throws ' + f.exception, () => {
const Q = Buffer.from(f.Q, 'hex');
assert.throws(() => {
__1.ECPair.fromPublicKey(Q, f.options);
}, new RegExp(f.exception));
});
});
});
describe('fromWIF', () => {
fixtures.valid.forEach(f => {
it('imports ' + f.WIF + ' (' + f.network + ')', () => {
const network = __2.networks[f.network];
const keyPair = __1.ECPair.fromWIF(f.WIF, network);
assert.strictEqual(keyPair.privateKey.toString('hex'), f.d);
assert.strictEqual(keyPair.compressed, f.compressed);
assert.strictEqual(keyPair.network, network);
});
});
fixtures.valid.forEach(f => {
it('imports ' + f.WIF + ' (via list of networks)', () => {
const keyPair = __1.ECPair.fromWIF(f.WIF, NETWORKS_LIST);
assert.strictEqual(keyPair.privateKey.toString('hex'), f.d);
assert.strictEqual(keyPair.compressed, f.compressed);
assert.strictEqual(keyPair.network, __2.networks[f.network]);
});
});
fixtures.invalid.fromWIF.forEach(f => {
it('throws on ' + f.WIF, () => {
assert.throws(() => {
const networks = f.network ? __2.networks[f.network] : NETWORKS_LIST;
__1.ECPair.fromWIF(f.WIF, networks);
}, new RegExp(f.exception));
});
});
});
describe('toWIF', () => {
fixtures.valid.forEach(f => {
it('exports ' + f.WIF, () => {
const keyPair = __1.ECPair.fromWIF(f.WIF, NETWORKS_LIST);
const result = keyPair.toWIF();
assert.strictEqual(result, f.WIF);
});
});
});
describe('makeRandom', () => {
const d = Buffer.alloc(32, 4);
const exWIF = 'KwMWvwRJeFqxYyhZgNwYuYjbQENDAPAudQx5VEmKJrUZcq6aL2pv';
describe('uses randombytes RNG', () => {
it('generates a ECPair', () => {
const stub = {
randombytes: () => {
return d;
},
};
const ProxiedECPair = proxyquire('../src/ecpair', stub);
const keyPair = ProxiedECPair.makeRandom();
assert.strictEqual(keyPair.toWIF(), exWIF);
});
});
it('allows a custom RNG to be used', () => {
const keyPair = __1.ECPair.makeRandom({
rng: (size) => {
return d.slice(0, size);
},
});
assert.strictEqual(keyPair.toWIF(), exWIF);
});
it('retains the same defaults as ECPair constructor', () => {
const keyPair = __1.ECPair.makeRandom();
assert.strictEqual(keyPair.compressed, true);
assert.strictEqual(keyPair.network, __2.networks.bitcoin);
});
it('supports the options parameter', () => {
const keyPair = __1.ECPair.makeRandom({
compressed: false,
network: __2.networks.testnet,
});
assert.strictEqual(keyPair.compressed, false);
assert.strictEqual(keyPair.network, __2.networks.testnet);
});
it('throws if d is bad length', () => {
function rng() {
return Buffer.alloc(28);
}
assert.throws(() => {
__1.ECPair.makeRandom({ rng });
}, /Expected Buffer\(Length: 32\), got Buffer\(Length: 28\)/);
});
it('loops until d is within interval [1, n) : 1', hoodwink(function () {
const rng = this.stub(() => {
if (rng.calls === 0)
return ZERO; // 0
return ONE; // >0
}, 2);
__1.ECPair.makeRandom({ rng });
}));
it('loops until d is within interval [1, n) : n - 1', hoodwink(function () {
const rng = this.stub(() => {
if (rng.calls === 0)
return ZERO; // <1
if (rng.calls === 1)
return GROUP_ORDER; // >n-1
return GROUP_ORDER_LESS_1; // n-1
}, 3);
__1.ECPair.makeRandom({ rng });
}));
});
describe('.network', () => {
fixtures.valid.forEach(f => {
it('returns ' + f.network + ' for ' + f.WIF, () => {
const network = __2.networks[f.network];
const keyPair = __1.ECPair.fromWIF(f.WIF, NETWORKS_LIST);
assert.strictEqual(keyPair.network, network);
});
});
});
describe('tinysecp wrappers', () => {
let keyPair;
let hash;
let signature;
beforeEach(() => {
keyPair = __1.ECPair.makeRandom();
hash = ZERO;
signature = Buffer.alloc(64, 1);
});
describe('signing', () => {
it('wraps tinysecp.sign', hoodwink(function () {
this.mock(tinysecp, 'sign', (h, d) => {
assert.strictEqual(h, hash);
assert.strictEqual(d, keyPair.privateKey);
return signature;
}, 1);
assert.strictEqual(keyPair.sign(hash), signature);
}));
it('throws if no private key is found', () => {
// @ts-ignore
delete keyPair.__D;
assert.throws(() => {
keyPair.sign(hash);
}, /Missing private key/);
});
});
describe('verify', () => {
it('wraps tinysecp.verify', hoodwink(function () {
this.mock(tinysecp, 'verify', (h, q, s) => {
assert.strictEqual(h, hash);
assert.strictEqual(q, keyPair.publicKey);
assert.strictEqual(s, signature);
return true;
}, 1);
assert.strictEqual(keyPair.verify(hash, signature), true);
}));
});
});
});