Skip to content
Open
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
ac2fe2a
init
hnsgrvr Feb 27, 2018
c3ba1d9
moved functions over, need new commit file from josh to import
hnsgrvr Mar 6, 2018
ac6a3d7
forgot to add exports
hnsgrvr Mar 6, 2018
37c63c7
moved everything over and deleted current dependencies in txs.ts, wia…
hnsgrvr Mar 6, 2018
93c27bc
Split txs.ts into multiple files based on stages
JWood323 Mar 20, 2018
71e0b31
added imports and exports to tx-commit
JWood323 Mar 20, 2018
de7a55c
finalized imports for genscripts file
hnsgrvr Mar 20, 2018
828ea7f
rename to preserve consistency
hnsgrvr Mar 20, 2018
12e824f
Merge branch 'generation-split' of https://github.com/colatkinson/bit…
JWood323 Mar 20, 2018
16c1b66
added changed imports from henrys file
JWood323 Mar 20, 2018
b69c275
added imports and exports
JWood323 Mar 20, 2018
3660c3b
updated gitignore bc its annoying
hnsgrvr Mar 20, 2018
52db608
added imports and exports
JWood323 Mar 20, 2018
9c5b99d
Merge branch 'generation-split' of https://github.com/colatkinson/bit…
JWood323 Mar 20, 2018
9b782ff
small fix to tx-generate
hnsgrvr Mar 20, 2018
c2b1b3d
edited tests to account for new files
JWood323 Mar 20, 2018
cac9834
updated txs tests file for refactored functions
hnsgrvr Mar 20, 2018
86fbad1
merge
hnsgrvr Mar 20, 2018
ca9e05f
edited tests to account for new files
JWood323 Mar 20, 2018
d910eb5
merge
hnsgrvr Mar 20, 2018
2b37bbd
Removed functions and exports in txs.ts
JWood323 Mar 20, 2018
a305087
few fixes
hnsgrvr Mar 20, 2018
39438ad
fixed error it txs
hnsgrvr Mar 27, 2018
3437192
missed importing a few functions
JWood323 Mar 27, 2018
90ed204
Merge branch 'generation-split' of https://github.com/colatkinson/bit…
JWood323 Mar 27, 2018
da7bce5
moved more imports
hnsgrvr Mar 27, 2018
b2c35db
adding more imports
JWood323 Mar 27, 2018
2152b9f
adding more imports
JWood323 Mar 27, 2018
651400d
adding more imports
JWood323 Mar 27, 2018
4b9d928
adding more imports
JWood323 Mar 27, 2018
84ee7e7
adding more imports
JWood323 Mar 27, 2018
1964d55
fixed errors and builds and runs correctly
JWood323 Mar 27, 2018
4db8cd1
Merge branch 'master' into generation-split
hgrov52 Apr 3, 2018
737fbc4
Merge branch 'master' into generation-split
colatkinson Apr 3, 2018
aa6db0e
Merge branch 'generation-split' of github.com:bitname-protocol/bitnam…
colatkinson Apr 3, 2018
0756d5e
Update bitname-cli.ts
hgrov52 Apr 5, 2018
38b4a4d
Merge branch 'master' into generation-split
hgrov52 Apr 16, 2018
b6e5644
syntax error
hgrov52 Apr 25, 2018
c8f1a9f
Merge branch 'master' of https://github.com/bitname-protocol/bitname-…
hgrov52 Apr 25, 2018
9586dc3
fixes for travis
hgrov52 Apr 25, 2018
ec46f5a
fixes for travis
hgrov52 Apr 25, 2018
4b3b937
fixes for travis
hgrov52 Apr 25, 2018
912d742
fixes for travis
hgrov52 Apr 25, 2018
c335240
fixes for travis
hgrov52 Apr 25, 2018
c9ff931
fixes for travis
hgrov52 Apr 25, 2018
0d9b384
fixes for travis
hgrov52 Apr 25, 2018
9af73b2
fixes for travis
hgrov52 Apr 25, 2018
957645b
fixes for travis
hgrov52 Apr 25, 2018
07c5e52
commented lines for code cov
hgrov52 Apr 25, 2018
02323a3
commented lines for code cov
hgrov52 Apr 25, 2018
ab746ae
commented lines for code cov
hgrov52 Apr 25, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,4 @@ typings/
# dotenv environment variables file
.env

package-lock.json
6 changes: 4 additions & 2 deletions __tests__/chain.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import { fundTx, getAllTX } from '../lib/net';

import { extractInfo } from '../lib/chain';

import TXList from '../lib/TXList';
import { genCommitTx, genLockTx, genUnlockTx } from '../lib/txs';
import TXList from '../lib/TXList';
import { genCommitTx } from '../lib/tx-commit.ts';
import { genLockTx } from '../lib/tx-lock.ts';
import { genUnlockTx } from '../lib/tx-unlock.ts';

describe('chain state', () => {
it('finds the one current name', async () => {
Expand Down
24 changes: 19 additions & 5 deletions __tests__/txs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,28 @@ import {
} from 'bcoin';

import {
genRedeemScript,
genLockTx,
genUnlockTx,
genCommitTx,
genCommitRedeemScript,
serializeCommitData,
deserializeCommitData,
} from '../lib/txs';

import {
genUnlockTx,
} from '../lib/tx-unlock';

import {
genLockTx,
} from '../lib/tx-lock';

import {
genCommitTx,
} from '../lib/tx-commit';


import {
genRedeemScript,
genCommitRedeemScript,
} from '../lib/tx-generate';

import {
BadUserPublicKeyError,
BadServicePublicKeyError,
Expand Down
9 changes: 6 additions & 3 deletions __tests__/verify.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import { verifyLockTX, verifyCommitTX } from '../lib/verify';
import {
genRedeemScript,
genP2shAddr,
genLockTx,
getLockTxName,
getLockTxPubKey,
getLockTxTime,
genCommitTx,
serializeCommitData,
deserializeCommitData,
} from '../lib/txs';
import{
genRedeemScript,
genCommitRedeemScript,
} from '../lib/tx-generate';
import { genCommitTx } from '../lib/tx-commit';
import { genLockTx } from '../lib/tx-lock';
import {
keyring as KeyRing,
coin as Coin,
Expand Down
124 changes: 124 additions & 0 deletions lib/tx-commit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import{
script as Script,
address as Address,
output as Output,
mtx as MTX,
coin as Coin,
tx as TX,
keyring as KeyRing,
crypto,
} from 'bcoin';

import{
genCommitRedeemScript,
} from './tx-generate';

import{
genP2shAddr,
} from './txs.ts';

import { verifyLockTX, isURISafe, verifyCommitTX } from './verify';

import randomBytes = require('randombytes');

/**
* Generate a commit transaction.
* @param coins Array of coins to fund the transaction.
* @param name Name for name/key pair.
* @param locktime Absolute locktime
* @param commitFee Commit fee, in satoshis.
* @param registerFee Registration fee, in satoshis.
* @param escrowFee Escrow fee, in satoshis.
* @param feeRate Fee rate, in satoshis/kilobyte.
* @param userRing The user's key ring.
* @param servicePubKey Service public key.
*/
function genCommitTx(coins: Coin[],
name: string,
locktime: number,
commitFee: number,
registerFee: number,
escrowFee: number,
feeRate: number,
userRing: KeyRing,
servicePubKey: Buffer): TX {
//
// Validate name and the service public key
if (name.length > 64) {
throw new Error('Name is too long');
}

if (!isURISafe(name)) {
throw new Error('Invalid character(s) in name');
}

if (!crypto.secp256k1.publicKeyVerify(servicePubKey)) {
throw new Error('Invalid service public key');
}

// Generate a P2SH address from a redeem script, using a random nonce
const nonce = randomBytes(32);
const redeemScript = genCommitRedeemScript(userRing.getPublicKey(), nonce, name, locktime);
const p2shAddr = genP2shAddr(redeemScript);

// Generate service address from service public key
const servicePKH = crypto.hash160(servicePubKey);
const serviceAddr = Address.fromPubkeyhash(servicePKH);

const lockTx = new MTX();

// Compute total value of coins
const total = coins.reduce((acc, cur) => acc + cur.value, 0);

for (const coin of coins) {
lockTx.addCoin(coin);
}

// Compute change amount
const changeVal = total - (commitFee + registerFee + escrowFee) - (4 * feeRate);

// Add nonce OP_RETURN as output 0
const pubkeyDataScript = Script.fromNulldata(nonce);
lockTx.addOutput(Output.fromScript(pubkeyDataScript, 0));

// Add service upfront fee as output 1
lockTx.addOutput({
address: serviceAddr,
value: commitFee,
});

// Add locked fee as output 2
// Locks up the fee to register, the fee to be put in escrow, and enough for a 4kb tx at current rates
lockTx.addOutput({
address: p2shAddr,
value: registerFee + escrowFee + 4 * feeRate,
});

// Add change output as 3
lockTx.addOutput({
address: userRing.getAddress(),
value: changeVal,
});

// Add coins as inputs
for (let i = 0; i < coins.length; ++i) {
const coin = coins[i];
lockTx.scriptInput(i, coin, userRing);
}

// Each signature is 72 bytes long
const virtSize = lockTx.getVirtualSize() + coins.length * 72;
lockTx.subtractIndex(3, Math.ceil(virtSize / 1000 * feeRate));

// Sign the coins
for (let i = 0; i < coins.length; ++i) {
const coin = coins[i];
lockTx.signInput(i, coin, userRing, Script.hashType.ALL);
}

return lockTx.toTX();

}
export {
genCommitTx
};
112 changes: 112 additions & 0 deletions lib/tx-generate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import {
script as Script,
crypto
} from 'bcoin';

import {
BadUserPublicKeyError,
BadServicePublicKeyError,
} from './errors';

import {
serializeCommitData,
} from './txs';

/**
* Generate a redeem script, removing a name/key pair from the blockchain.
* Validates `userPubkey` and `servicePubkey`.
*
* @param userPubkey The user's public key.
* @param servicePubkey The service's public key.
* @param alocktime An absolute lock time, in blocks.
*/
function genRedeemScript(userPubkey: Buffer, servicePubkey: Buffer, alocktime: number): Script {
// Validate user public key
if (!crypto.secp256k1.publicKeyVerify(userPubkey)) {
throw new BadUserPublicKeyError();
}

// Validate service public key
if (!crypto.secp256k1.publicKeyVerify(servicePubkey)) {
throw new BadServicePublicKeyError();
}

const script = new Script(null);

script.pushSym('OP_IF');

//
// If spending as user, execute this branch

// Verify that 0 <= current block size - commit block size
script.pushInt(0);
script.pushSym('OP_CHECKSEQUENCEVERIFY');
script.pushSym('OP_DROP');

// Check the provided user signature
script.pushData(userPubkey);
script.pushSym('OP_CHECKSIG');

script.pushSym('OP_ELSE');

//
// Otherwise, if spending as service, execute this branch

// Verify that alocktime <= current block size
script.pushInt(alocktime);
script.pushSym('OP_CHECKLOCKTIMEVERIFY');
script.pushSym('OP_DROP');

// Check the provided service signature
script.pushData(servicePubkey);
script.pushSym('OP_CHECKSIG');

script.pushSym('OP_ENDIF');

script.compile();

return script;
}

/**
* Generate a commit redeem script.
* @param userPubkey The user's public key.
* @param nonce A 256-bit buffer representing a nonce.
* @param name A name of at most 64 characters composed of URL-safe characters.
* @param locktime An absolute lock time, in blocks.
*/
function genCommitRedeemScript(userPubkey: Buffer, nonce: Buffer, name: string, locktime: number): Script {
// Validate user public key
if (!crypto.secp256k1.publicKeyVerify(userPubkey)) {
throw new BadUserPublicKeyError();
}

const script = new Script();

// Verify that at least six blocks have passed since commit
script.pushInt(6);
script.pushSym('OP_CHECKSEQUENCEVERIFY');
script.pushSym('OP_DROP');

//
// Hash [256-bit nonce + 2-byte locktime (BE) + 1-byte length of name + name]
// and check against parameters.
script.pushSym('OP_HASH256');

const hashData = serializeCommitData(nonce, locktime, name);
const hash = crypto.hash256(hashData);
script.pushData(hash);
script.pushSym('OP_EQUALVERIFY');

// Check user signature
script.pushData(userPubkey);
script.pushSym('OP_CHECKSIG');

script.compile();
return script;
}

export {
genRedeemScript,
genCommitRedeemScript,
};
Loading