Skip to content

Commit e63778f

Browse files
committed
ref!: remove keys array entirely
1 parent 6030f3d commit e63778f

File tree

5 files changed

+107
-88
lines changed

5 files changed

+107
-88
lines changed

bin/create-memo.js

+20-10
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,6 @@ let DashTx = require("../");
1111
let DashKeys = require("dashkeys");
1212
let Secp256k1 = require("@dashincubator/secp256k1");
1313

14-
/** @type {import('../dashtx.js').TxSign} */
15-
async function signTx(privKeyBytes, hashBytes) {
16-
let sigOpts = { canonical: true };
17-
let sigBuf = await Secp256k1.sign(hashBytes, privKeyBytes, sigOpts);
18-
return sigBuf;
19-
}
20-
2114
async function main() {
2215
let args = process.argv.slice(2);
2316

@@ -77,7 +70,6 @@ async function main() {
7770
let dash = toDash(coreUtxo.satoshis);
7871
console.info(`Coin Value: ${dash} (${duffs})`);
7972

80-
let keys = [privKeyBytes];
8173
let inputs = [coreUtxo];
8274
let outputs = [{ memo: memo, satoshis: 0 }];
8375

@@ -106,11 +98,29 @@ async function main() {
10698
//change.satoshis = sats;
10799

108100
let dashTx = DashTx.create({
109-
sign: signTx,
101+
/** @type {import('../dashtx.js').TxSign} */
102+
sign: async function (privKeyBytes, hashBytes) {
103+
let sigOpts = { canonical: true };
104+
let sigBuf = await Secp256k1.sign(hashBytes, privKeyBytes, sigOpts);
105+
return sigBuf;
106+
},
107+
getPrivateKey: async function () {
108+
return privKeyBytes;
109+
},
110+
toPublicKey:
111+
/**
112+
* @param {Uint8Array} privBytes
113+
* @returns {Promise<Uint8Array>}
114+
*/
115+
async function (privBytes) {
116+
let isCompressed = true;
117+
let pubBytes = Secp256k1.getPublicKey(privBytes, isCompressed);
118+
return pubBytes;
119+
},
110120
});
111121

112122
//@ts-ignore
113-
let txInfoSigned = await dashTx.hashAndSignAll(txInfo, keys);
123+
let txInfoSigned = await dashTx.hashAndSignAll(txInfo);
114124
let txHex = txInfoSigned.transaction.toString();
115125

116126
console.info();

dashtx.js

+23-39
Original file line numberDiff line numberDiff line change
@@ -231,16 +231,9 @@ var DashTx = ("object" === typeof module && exports) || {};
231231
let txInst = {};
232232

233233
/** @type {TxHashAndSignAll} */
234-
txInst.hashAndSignAll = async function (txInfo, keys) {
234+
txInst.hashAndSignAll = async function (txInfo) {
235235
let privUtils = keyUtils;
236-
if (keys) {
237-
if (keys.length !== txInfo.inputs.length) {
238-
let msg = `the number and order of 'keys' must match number of 'inputs' - each 'utxo' of the provided private key must be matched to that private key`;
239-
throw new Error(msg);
240-
}
241-
privUtils = Object.assign({}, keyUtils);
242-
}
243-
void Tx._addPrivKeyUtils(privUtils, keys);
236+
void Tx._addPrivKeyUtils(privUtils);
244237

245238
return await Tx._hashAndSignAll(txInfo, privUtils);
246239
};
@@ -323,19 +316,18 @@ var DashTx = ("object" === typeof module && exports) || {};
323316

324317
/**
325318
* @param {TxDraft} txDraft
326-
* @param {Array<TxPrivateKey>} keys
327319
* @returns {Promise<TxSummary>}
328320
*/
329-
txInst.legacy.finalizePresorted = async function (txDraft, keys) {
321+
txInst.legacy.finalizePresorted = async function (txDraft) {
330322
/** @type {TxInfoSigned} */
331323
let txSigned = await txInst.legacy
332-
._signToTarget(txDraft, keys)
324+
._signToTarget(txDraft)
333325
.catch(async function (e) {
334326
if ("E_NO_ENTROPY" !== e.code) {
335327
throw e;
336328
}
337329

338-
let _txSigned = await txInst.legacy._signFeeWalk(txDraft, keys);
330+
let _txSigned = await txInst.legacy._signFeeWalk(txDraft);
339331
return _txSigned;
340332
});
341333

@@ -345,10 +337,9 @@ var DashTx = ("object" === typeof module && exports) || {};
345337

346338
/**
347339
* @param {TxDraft} txDraft
348-
* @param {Array<Uint8Array>} keys
349340
* @returns {Promise<TxInfoSigned>}
350341
*/
351-
txInst.legacy._signToTarget = async function (txDraft, keys) {
342+
txInst.legacy._signToTarget = async function (txDraft) {
352343
let limit = 128;
353344
let lastTx = "";
354345
let hasEntropy = true;
@@ -358,7 +349,7 @@ var DashTx = ("object" === typeof module && exports) || {};
358349
let fee;
359350

360351
for (let n = 0; true; n += 1) {
361-
txSigned = await txInst.hashAndSignAll(txDraft, keys);
352+
txSigned = await txInst.hashAndSignAll(txDraft);
362353

363354
fee = txSigned.transaction.length / 2;
364355
if (fee <= txDraft.feeTarget) {
@@ -391,10 +382,9 @@ var DashTx = ("object" === typeof module && exports) || {};
391382
* Strategy for signing transactions when a non-entropy signing method is used -
392383
* exhaustively walk each possible signature until one that works is found.
393384
* @param {TxDraft} txDraft
394-
* @param {Array<Uint8Array>} keys
395385
* @returns {Promise<TxInfoSigned>}
396386
*/
397-
txInst.legacy._signFeeWalk = async function (txDraft, keys) {
387+
txInst.legacy._signFeeWalk = async function (txDraft) {
398388
//@ts-ignore - TODO should have satoshis by now
399389
let totalIn = DashTx.sum(txDraft.inputs);
400390
let totalOut = DashTx.sum(txDraft.outputs);
@@ -424,7 +414,7 @@ var DashTx = ("object" === typeof module && exports) || {};
424414
txDraft.outputs[outIndex].satoshis -= 1;
425415
totalFee += 1;
426416

427-
txSigned = await txInst.hashAndSignAll(txDraft, keys);
417+
txSigned = await txInst.hashAndSignAll(txDraft);
428418

429419
let byteFee = txSigned.transaction.length / 2;
430420
if (byteFee <= totalFee) {
@@ -627,8 +617,8 @@ var DashTx = ("object" === typeof module && exports) || {};
627617
* - ASC `outputIndex` (a.k.a. `output_index`, `vout`)
628618
*/
629619
Tx.sortInputs = function (a, b) {
630-
let aTxid = a.txid || a.txId;
631-
let bTxid = b.txid || b.txId;
620+
let aTxid = a.txId || a.txid;
621+
let bTxid = b.txId || b.txid;
632622
// Ascending Lexicographical on TxId (prev-hash) in-memory (not wire) byte order
633623
if (aTxid > bTxid) {
634624
return 1;
@@ -735,19 +725,10 @@ var DashTx = ("object" === typeof module && exports) || {};
735725

736726
/**
737727
* @param {TxDeps} privUtils
738-
* @param {Array<TxPrivateKey>} keys
739728
*/
740-
Tx._addPrivKeyUtils = function (privUtils, keys) {
729+
Tx._addPrivKeyUtils = function (privUtils) {
741730
if (!privUtils.getPrivateKey) {
742-
if (!keys) {
743-
throw new Error(`you must create with 'getPrivateKey()'`);
744-
}
745-
/** @type {TxGetPrivateKey} */
746-
privUtils.getPrivateKey = async function (_, i) {
747-
//@ts-ignore - keys *is* defined, see above
748-
let privKey = keys[i];
749-
return privKey;
750-
};
731+
throw new Error(`you must create with 'opts.getPrivateKey()'`);
751732
}
752733

753734
if (!privUtils.getPublicKey) {
@@ -1619,7 +1600,7 @@ if ("object" === typeof module) {
16191600

16201601
/**
16211602
* @typedef CoreUtxo
1622-
* @property {String} txId
1603+
* @property {String} txid
16231604
* @property {Number} outputIndex
16241605
* @property {String} address
16251606
* @property {String} script
@@ -1685,7 +1666,8 @@ if ("object" === typeof module) {
16851666
/**
16861667
* @typedef TxInput
16871668
* @prop {String} [address] - BaseCheck58-encoded pubKeyHash
1688-
* @prop {String} txId - hex (not pre-reversed)
1669+
* @prop {String} [txId] - deprecated
1670+
* @prop {String} txid - hex (not pre-reversed)
16891671
* @prop {Uint32} outputIndex - index in previous tx's output (vout index)
16901672
* @prop {String} signature - hex-encoded ASN.1 (DER) signature (starts with 0x30440220 or 0x30440221)
16911673
* @prop {String} [script] - the previous lock script (default: derived from public key as p2pkh)
@@ -1712,21 +1694,24 @@ if ("object" === typeof module) {
17121694
* @typedef TxInputRaw
17131695
* @prop {String} [address] - BaseCheck58-encoded pubKeyHash
17141696
* @prop {Uint53} [satoshis] - for convenience
1715-
* @prop {String} txId - hex (not pre-reversed)
1697+
* @prop {String} [txId] - deprecated
1698+
* @prop {String} txid - hex (not pre-reversed)
17161699
* @prop {Uint32} outputIndex - index in previous tx's output (vout index)
17171700
*/
17181701

17191702
/**
17201703
* @typedef TxInputUnspent
17211704
* @prop {String} [address] - BaseCheck58-encoded pubKeyHash
17221705
* @prop {Uint53} satoshis
1723-
* @prop {String} txId - hex (not pre-reversed)
1706+
* @prop {String} [txId] - deprecated
1707+
* @prop {String} txid - hex (not pre-reversed)
17241708
* @prop {Uint32} outputIndex - index in previous tx's output (vout index)
17251709
*/
17261710

17271711
/**
17281712
* @typedef TxInputSortable
1729-
* @prop {String} txId
1713+
* @prop {String} [txId] - deprecated
1714+
* @prop {String} txid
17301715
* @prop {Uint32} outputIndex
17311716
*/
17321717

@@ -1736,7 +1721,7 @@ if ("object" === typeof module) {
17361721
*/
17371722

17381723
/**
1739-
* @typedef {Pick<TxInput, "txId"|"outputIndex"|"signature"|"publicKey"|"sigHashType">} TxInputSigned
1724+
* @typedef {Pick<TxInput, "txid"|"txId"|"outputIndex"|"signature"|"publicKey"|"sigHashType">} TxInputSigned
17401725
*/
17411726

17421727
/**
@@ -1848,7 +1833,6 @@ if ("object" === typeof module) {
18481833
/**
18491834
* @callback TxHashAndSignAll
18501835
* @param {TxInfo} txInfo
1851-
* @param {Array<TxPrivateKey>} [keys]
18521836
*/
18531837

18541838
/**

tests/legacy-draft.js

+26-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
let DashTx = require("../");
44

5+
let Secp256k1 = require("@dashincubator/secp256k1");
6+
57
// generated with https://webinstall.dev/dashmsg
68
// dashmsg gen --cointype '4c' ./test-1.wif
79
// dashmsg inspect --cointype '4c' "$(cat ./test-1.wif)"
@@ -43,7 +45,30 @@ let tests = [
4345
];
4446

4547
async function test() {
46-
let dashTx = DashTx.create();
48+
let keyUtils = {
49+
getPrivateKey: async function (txInput, i) {
50+
let pkhBytes = DashKeys.utils.hexToBytes(txInput.pubKeyHash);
51+
let address = await DashKeys.pkhToAddr(txInput.pubKeyHash);
52+
53+
let yourKeyData = yourWalletKeyMapGoesHere[address];
54+
55+
let privKeyBytes = DashKeys.wifToPrivKey(yourKeyData.wif);
56+
return privKeyBytes;
57+
},
58+
sign: async function (privKeyBytes, txHashBytes) {
59+
let sigOpts = { canonical: true, extraEntropy: true };
60+
let sigBytes = await Secp256k1.sign(txHashBytes, privKeyBytes, sigOpts);
61+
62+
return sigBytes;
63+
},
64+
toPublicKey: async function (privKeyBytes) {
65+
let isCompressed = true;
66+
let pubKeyBytes = Secp256k1.getPublicKey(privKeyBytes, isCompressed);
67+
68+
return pubKeyBytes;
69+
},
70+
};
71+
let dashTx = DashTx.create(keyUtils);
4772

4873
for (let t of tests) {
4974
let exp = t.expected;

tests/legacy-finalize-presorted.js

+27-26
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,6 @@ let DashTx = require("../");
55
let DashKeys = require("dashkeys");
66
let Secp256k1 = require("@dashincubator/secp256k1");
77

8-
let keyUtils = {
9-
sign: async function (privKeyBytes, hashBytes) {
10-
let sigOpts = {
11-
canonical: true,
12-
extraEntropy: true,
13-
};
14-
let sigBuf = await Secp256k1.sign(hashBytes, privKeyBytes, sigOpts);
15-
return sigBuf;
16-
},
17-
toPublicKey: async function (privKeyBytes) {
18-
return DashKeys.utils.toPublicKey(privKeyBytes);
19-
},
20-
};
21-
228
// generated with https://webinstall.dev/dashmsg
239
// dashmsg gen --cointype '4c' ./test-1.wif
2410
// dashmsg inspect --cointype '4c' "$(cat ./test-1.wif)"
@@ -90,7 +76,31 @@ function genTestVals(name, sats, deterministic) {
9076

9177
async function testAll() {
9278
async function setupAndRunOne(original) {
79+
let keyUtils = {
80+
sign: async function (privKeyBytes, hashBytes) {
81+
let sigOpts = {
82+
canonical: true,
83+
extraEntropy: true,
84+
};
85+
let sigBuf = await Secp256k1.sign(hashBytes, privKeyBytes, sigOpts);
86+
return sigBuf;
87+
},
88+
toPublicKey: async function (privKeyBytes) {
89+
return DashKeys.utils.toPublicKey(privKeyBytes);
90+
},
91+
getPrivateKey: async function (txInput) {
92+
let wif = original.wifs[txInput.address];
93+
if (!wif) {
94+
let msg = `no WIF found for pubKeyAddr '${txInput.address}' (${txInput.satoshis})`;
95+
throw new Error(msg);
96+
}
97+
98+
let privKeyBytes = await DashKeys.wifToPrivKey(wif);
99+
return privKeyBytes;
100+
},
101+
};
93102
let dashTx = DashTx.create(keyUtils);
103+
94104
let t1 = JSON.parse(JSON.stringify(original));
95105
let t2 = JSON.parse(JSON.stringify(original));
96106
let txDraft = dashTx.legacy.draftSingleOutput({
@@ -101,18 +111,9 @@ async function testAll() {
101111
txDraft.inputs.sort(DashTx.sortInputs);
102112
txDraft.outputs.sort(DashTx.sortOutputs);
103113

104-
let keys = [];
105114
for (let input of txDraft.inputs) {
106115
let pkhBytes = await DashKeys.addrToPkh(input.address);
107116
input.pubKeyHash = DashKeys.utils.bytesToHex(pkhBytes);
108-
109-
let wif = t1.wifs[input.address];
110-
let key = await DashKeys.wifToPrivKey(wif);
111-
if (!key) {
112-
let msg = `no WIF found for pubKeyAddr '${input.address}' (${input.satoshis})`;
113-
throw new Error(msg);
114-
}
115-
keys.push(key);
116117
}
117118

118119
for (let output of txDraft.outputs) {
@@ -128,7 +129,7 @@ async function testAll() {
128129
}
129130
let myDashTx = DashTx.create(_keyUtils);
130131

131-
await testOne(myDashTx, t2, txDraft, keys, rndIters).catch(function (err) {
132+
await testOne(myDashTx, t2, txDraft, rndIters).catch(function (err) {
132133
console.info(`# failed ${t1.name}`);
133134
console.info(`# txDraft`, txDraft);
134135
if (err.txSummary) {
@@ -162,12 +163,12 @@ function createNonRndSigner() {
162163
return nonRndSign;
163164
}
164165

165-
async function testOne(myDashTx, original, txDraft, keys, rndIters) {
166+
async function testOne(myDashTx, original, txDraft, rndIters) {
166167
for (let seedIterations = 0; seedIterations < rndIters; seedIterations += 1) {
167168
let t = JSON.parse(JSON.stringify(original));
168169
let exp = t.expected;
169170

170-
let txSummary = await myDashTx.legacy.finalizePresorted(txDraft, keys);
171+
let txSummary = await myDashTx.legacy.finalizePresorted(txDraft);
171172
let txByteSize = txSummary.transaction.length / 2;
172173
// console.log("[DEBUG] txSummary");
173174
// console.log(txByteSize, txSummary.fee);

0 commit comments

Comments
 (0)