Skip to content

Commit 7326600

Browse files
authored
Merge pull request #265 from sCrypt-Inc/hash-cache
add hash cache
2 parents 4cc1967 + 95458a7 commit 7326600

7 files changed

Lines changed: 103 additions & 30 deletions

File tree

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "scryptlib",
3-
"version": "2.1.41",
3+
"version": "2.1.42",
44
"description": "Javascript SDK for integration of Bitcoin SV Smart Contracts written in sCrypt language.",
55
"engines": {
66
"node": ">=14.0.0"
@@ -76,4 +76,4 @@
7676
"yargs": "^17.6.2",
7777
"chalk": "2.4.2"
7878
}
79-
}
79+
}

patches/bsv/index.d.ts

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -753,24 +753,16 @@ declare module 'bsv' {
753753
}
754754

755755
class Point {
756-
constructor(x: crypto.BN | string,
757-
y: crypto.BN | string,
758-
isRed: boolean);
759-
760756
static fromX(odd: boolean, x: crypto.BN | string): Point;
761757
static getG(): any;
762758
static getN(): crypto.BN;
763759
getX(): crypto.BN;
764760
getY(): crypto.BN;
765761
validate(): this;
766762
mul(n: crypto.BN): Point;
767-
add(n: crypto.Point): Point;
768-
neg(): Point;
769763
}
770764

771765
class Signature {
772-
constructor(r: crypto.BN, s: crypto.BN);
773-
774766
static fromDER(sig: Buffer): Signature;
775767
static fromTxFormat(buf: Buffer): Signature;
776768
static fromString(data: string): Signature;
@@ -873,15 +865,17 @@ declare module 'bsv' {
873865
inputNumber: number,
874866
subscript: Script,
875867
satoshisBN: crypto.BN,
876-
flags?: number
868+
flags?: number,
869+
hashCache?: HashCache
877870
): Buffer;
878871
function sighash(
879872
transaction: Transaction,
880873
sighashType: number,
881874
inputNumber: number,
882875
subscript: Script,
883876
satoshisBN: crypto.BN,
884-
flags?: number
877+
flags?: number,
878+
hashCache?: HashCache
885879
): Buffer;
886880
function sign(
887881
transaction: Transaction,
@@ -890,7 +884,8 @@ declare module 'bsv' {
890884
inputIndex: number,
891885
subscript: Script,
892886
satoshisBN: crypto.BN,
893-
flags?: number
887+
flags?: number,
888+
hashCache?: HashCache
894889
): crypto.Signature;
895890
function verify(
896891
transaction: Transaction,
@@ -899,7 +894,8 @@ declare module 'bsv' {
899894
inputIndex: number,
900895
subscript: Script,
901896
satoshisBN: crypto.BN,
902-
flags?: number
897+
flags?: number,
898+
hashCache?: HashCache
903899
): boolean;
904900
}
905901
}
@@ -1486,4 +1482,20 @@ declare module 'bsv' {
14861482
flags: Array<number>;
14871483
};
14881484
}
1489-
}
1485+
1486+
export class HashCache {
1487+
constructor(
1488+
prevoutsHashBuf?: Buffer,
1489+
sequenceHashBuf?: Buffer,
1490+
outputsHashBuf?: Buffer
1491+
)
1492+
1493+
static fromBuffer(buf: Buffer): HashCache
1494+
static fromJSON(json: object): HashCache
1495+
static fromHex(hex: string): HashCache
1496+
1497+
toBuffer(): HashCache
1498+
toJSON(): HashCache
1499+
toHex(): HashCache
1500+
}
1501+
}

patches/bsv/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ bsv.PublicKey = require('./lib/publickey')
5555
bsv.Script = require('./lib/script')
5656
bsv.Transaction = require('./lib/transaction')
5757
bsv.ECIES = require('./lib/ecies')
58+
bsv.HashCache = require('./lib/hash-cache')
5859

5960
// dependencies, subject to change
6061
bsv.deps = {}

patches/bsv/lib/hash-cache.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* Hash Cache
3+
* ==========
4+
*
5+
* For use in sighash.
6+
*/
7+
'use strict'
8+
9+
class HashCache {
10+
constructor (prevoutsHashBuf, sequenceHashBuf, outputsHashBuf) {
11+
this.prevoutsHashBuf = prevoutsHashBuf
12+
this.sequenceHashBuf = sequenceHashBuf
13+
this.outputsHashBuf = outputsHashBuf
14+
}
15+
16+
static fromBuffer (buf) {
17+
return HashCache.fromJSON(JSON.parse(buf.toString()))
18+
}
19+
20+
toBuffer () {
21+
return Buffer.from(JSON.stringify(this.toJSON()))
22+
}
23+
24+
static fromJSON (json) {
25+
return new HashCache(
26+
json.prevoutsHashBuf ? Buffer.from(json.prevoutsHashBuf, 'hex') : undefined,
27+
json.sequenceHashBuf ? Buffer.from(json.sequenceHashBuf, 'hex') : undefined,
28+
json.outputsHashBuf ? Buffer.from(json.outputsHashBuf, 'hex') : undefined
29+
)
30+
}
31+
32+
toJSON () {
33+
return {
34+
prevoutsHashBuf: this.prevoutsHashBuf ? this.prevoutsHashBuf.toString('hex') : undefined,
35+
sequenceHashBuf: this.sequenceHashBuf ? this.sequenceHashBuf.toString('hex') : undefined,
36+
outputsHashBuf: this.outputsHashBuf ? this.outputsHashBuf.toString('hex') : undefined
37+
}
38+
}
39+
40+
toHex () {
41+
return this.toBuffer().toString('hex')
42+
}
43+
44+
static fromHex (hex) {
45+
const buf = Buffer.from(hex, 'hex')
46+
return HashCache.fromBuffer(buf)
47+
}
48+
}
49+
50+
module.exports = HashCache

patches/bsv/lib/transaction/sighash.js

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,15 @@ var ECDSA = require('../crypto/ecdsa')
1313
var $ = require('../util/preconditions')
1414
var Interpreter = require('../script/interpreter')
1515
var _ = require('../util/_')
16+
var HashCache = require('../hash-cache')
1617

1718
var SIGHASH_SINGLE_BUG = Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex')
1819
var BITS_64_ON = 'ffffffffffffffff'
1920

2021
// By default, we sign with sighash_forkid
2122
var DEFAULT_SIGN_FLAGS = Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID
2223

23-
var sighashPreimageForForkId = function (transaction, sighashType, inputNumber, subscript, satoshisBN) {
24+
var sighashPreimageForForkId = function (transaction, sighashType, inputNumber, subscript, satoshisBN, hashCache = new HashCache()) {
2425
var input = transaction.inputs[inputNumber]
2526
$.checkArgument(
2627
satoshisBN instanceof BN,
@@ -73,17 +74,17 @@ var sighashPreimageForForkId = function (transaction, sighashType, inputNumber,
7374
var hashOutputs = Buffer.alloc(32)
7475

7576
if (!(sighashType & Signature.SIGHASH_ANYONECANPAY)) {
76-
hashPrevouts = GetPrevoutHash(transaction)
77+
hashPrevouts = hashCache.prevoutsHashBuf ? hashCache.prevoutsHashBuf : hashCache.prevoutsHashBuf = GetPrevoutHash(transaction)
7778
}
7879

7980
if (!(sighashType & Signature.SIGHASH_ANYONECANPAY) &&
8081
(sighashType & 31) !== Signature.SIGHASH_SINGLE &&
8182
(sighashType & 31) !== Signature.SIGHASH_NONE) {
82-
hashSequence = GetSequenceHash(transaction)
83+
hashSequence = hashCache.sequenceHashBuf ? hashCache.sequenceHashBuf : hashCache.sequenceHashBuf = GetSequenceHash(transaction)
8384
}
8485

8586
if ((sighashType & 31) !== Signature.SIGHASH_SINGLE && (sighashType & 31) !== Signature.SIGHASH_NONE) {
86-
hashOutputs = GetOutputsHash(transaction)
87+
hashOutputs = hashCache.outputsHashBuf ? hashCache.outputsHashBuf : hashCache.outputsHashBuf = GetOutputsHash(transaction)
8788
} else if ((sighashType & 31) === Signature.SIGHASH_SINGLE && inputNumber < transaction.outputs.length) {
8889
hashOutputs = GetOutputsHash(transaction, inputNumber)
8990
}
@@ -136,7 +137,7 @@ var sighashPreimageForForkId = function (transaction, sighashType, inputNumber,
136137
* @param {satoshisBN} input's amount (for ForkId signatures)
137138
*
138139
*/
139-
var sighashPreimage = function sighashPreimage (transaction, sighashType, inputNumber, subscript, satoshisBN, flags) {
140+
var sighashPreimage = function sighashPreimage (transaction, sighashType, inputNumber, subscript, satoshisBN, flags, hashCache = new HashCache()) {
140141
var Transaction = require('./transaction')
141142
var Input = require('./input')
142143

@@ -227,8 +228,8 @@ var sighashPreimage = function sighashPreimage (transaction, sighashType, inputN
227228
* @param {satoshisBN} input's amount (for ForkId signatures)
228229
*
229230
*/
230-
var sighash = function sighash (transaction, sighashType, inputNumber, subscript, satoshisBN, flags) {
231-
var preimage = sighashPreimage(transaction, sighashType, inputNumber, subscript, satoshisBN, flags)
231+
var sighash = function sighash (transaction, sighashType, inputNumber, subscript, satoshisBN, flags, hashCache = new HashCache()) {
232+
var preimage = sighashPreimage(transaction, sighashType, inputNumber, subscript, satoshisBN, flags, hashCache)
232233
if (preimage.compare(SIGHASH_SINGLE_BUG) === 0) return preimage
233234
var ret = Hash.sha256sha256(preimage)
234235
ret = new BufferReader(ret).readReverse()
@@ -247,8 +248,8 @@ var sighash = function sighash (transaction, sighashType, inputNumber, subscript
247248
* @param {satoshisBN} input's amount
248249
* @return {Signature}
249250
*/
250-
function sign (transaction, privateKey, sighashType, inputIndex, subscript, satoshisBN, flags) {
251-
var hashbuf = sighash(transaction, sighashType, inputIndex, subscript, satoshisBN, flags)
251+
function sign (transaction, privateKey, sighashType, inputIndex, subscript, satoshisBN, flags, hashCache = new HashCache()) {
252+
var hashbuf = sighash(transaction, sighashType, inputIndex, subscript, satoshisBN, flags, hashCache)
252253

253254
var sig = ECDSA.sign(hashbuf, privateKey, 'little').set({
254255
nhashtype: sighashType
@@ -269,10 +270,10 @@ function sign (transaction, privateKey, sighashType, inputIndex, subscript, sato
269270
* @param {flags} verification flags
270271
* @return {boolean}
271272
*/
272-
function verify (transaction, signature, publicKey, inputIndex, subscript, satoshisBN, flags) {
273+
function verify (transaction, signature, publicKey, inputIndex, subscript, satoshisBN, flags, hashCache = new HashCache()) {
273274
$.checkArgument(!_.isUndefined(transaction))
274275
$.checkArgument(!_.isUndefined(signature) && !_.isUndefined(signature.nhashtype))
275-
var hashbuf = sighash(transaction, signature.nhashtype, inputIndex, subscript, satoshisBN, flags)
276+
var hashbuf = sighash(transaction, signature.nhashtype, inputIndex, subscript, satoshisBN, flags, hashCache)
276277
return ECDSA.verify(hashbuf, signature, publicKey, 'little')
277278
}
278279

src/utils.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,16 @@ export function hexStringToBytes(hex: string): number[] {
165165
}
166166

167167

168-
export function signTx(tx: bsv.Transaction, privateKey: bsv.PrivateKey, lockingScript: Script, inputAmount: number, inputIndex = 0, sighashType = DEFAULT_SIGHASH_TYPE, flags = DEFAULT_FLAGS): string {
168+
export function signTx(
169+
tx: bsv.Transaction,
170+
privateKey: bsv.PrivateKey,
171+
lockingScript: Script,
172+
inputAmount: number,
173+
inputIndex = 0,
174+
sighashType = DEFAULT_SIGHASH_TYPE,
175+
flags = DEFAULT_FLAGS,
176+
hashCache?: bsv.HashCache
177+
): string {
169178

170179
if (!tx) {
171180
throw new Error('param tx can not be empty');
@@ -189,7 +198,7 @@ export function signTx(tx: bsv.Transaction, privateKey: bsv.PrivateKey, lockingS
189198

190199
return toHex(bsv.Transaction.Sighash.sign(
191200
tx, privateKey, sighashType, inputIndex,
192-
lockingScript, new bsv.crypto.BN(inputAmount), flags
201+
lockingScript, new bsv.crypto.BN(inputAmount), flags, hashCache
193202
).toTxFormat());
194203
}
195204

0 commit comments

Comments
 (0)