@smartledger/bsv 9.10.0 → 9.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +68 -0
- package/README.md +19 -19
- package/bsv-gdaf.min.js +58 -58
- package/bsv-ltp.min.js +28 -28
- package/bsv-smartcontract.min.js +1 -1
- package/bsv.bundle.js +58 -58
- package/bsv.min.js +58 -58
- package/docs/AUDIT_SCOPE.md +8 -8
- package/docs/BRC220_CERTIFICATE_FIELDS_AMENDMENT.md +7 -3
- package/docs/MODULE_REFERENCE_COMPLETE.md +27 -27
- package/docs/advanced/UTXO_MANAGER_GUIDE.md +1 -1
- package/docs/audit-rfq/cure53.txt +2 -2
- package/docs/audit-rfq/ncc-group.txt +2 -2
- package/docs/audit-rfq/trail-of-bits.txt +2 -2
- package/docs/getting-started/INSTALLATION.md +23 -23
- package/docs/getting-started/QUICK_START.md +7 -7
- package/docs/migration/FROM_BSV_1_5_6.md +5 -5
- package/lib/notaryhash/suites.js +2 -2
- package/lib/script/interpreter.js +40 -10
- package/lib/script/script.js +72 -21
- package/lib/transaction/sighash.js +12 -5
- package/package.json +1 -1
- package/version.js +1 -1
package/lib/script/script.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
var assert = require('assert')
|
|
4
|
+
|
|
3
5
|
var Address = require('../address')
|
|
4
6
|
var BufferReader = require('../encoding/bufferreader')
|
|
5
|
-
var BufferWriter = require('../encoding/bufferwriter')
|
|
6
7
|
var Hash = require('../crypto/hash')
|
|
7
8
|
var Opcode = require('../opcode')
|
|
8
9
|
var PublicKey = require('../publickey')
|
|
@@ -107,29 +108,59 @@ Script.fromBuffer = function (buffer) {
|
|
|
107
108
|
}
|
|
108
109
|
|
|
109
110
|
Script.prototype.toBuffer = function () {
|
|
110
|
-
|
|
111
|
+
// Sized first and written into one allocation. A locking script can have
|
|
112
|
+
// hundreds of thousands of chunks, and this runs for every signature check
|
|
113
|
+
// over it; a writer that allocates per chunk made that the dominant cost.
|
|
114
|
+
// Writes go through Buffer's checked writers, so a malformed chunk throws
|
|
115
|
+
// exactly where the per-chunk writer threw.
|
|
116
|
+
var chunks = this.chunks
|
|
117
|
+
var size = 0
|
|
118
|
+
var i, chunk, opcodenum
|
|
119
|
+
for (i = 0; i < chunks.length; i++) {
|
|
120
|
+
chunk = chunks[i]
|
|
121
|
+
opcodenum = chunk.opcodenum
|
|
122
|
+
size += 1
|
|
123
|
+
if (chunk.buf) {
|
|
124
|
+
if (opcodenum < Opcode.OP_PUSHDATA1) {
|
|
125
|
+
size += bufLength(chunk.buf)
|
|
126
|
+
} else if (opcodenum === Opcode.OP_PUSHDATA1) {
|
|
127
|
+
size += 1 + bufLength(chunk.buf)
|
|
128
|
+
} else if (opcodenum === Opcode.OP_PUSHDATA2) {
|
|
129
|
+
size += 2 + bufLength(chunk.buf)
|
|
130
|
+
} else if (opcodenum === Opcode.OP_PUSHDATA4) {
|
|
131
|
+
size += 4 + bufLength(chunk.buf)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
111
135
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
136
|
+
var out = Buffer.alloc(size)
|
|
137
|
+
var o = 0
|
|
138
|
+
for (i = 0; i < chunks.length; i++) {
|
|
139
|
+
chunk = chunks[i]
|
|
140
|
+
opcodenum = chunk.opcodenum
|
|
141
|
+
o = out.writeUInt8(chunk.opcodenum, o)
|
|
116
142
|
if (chunk.buf) {
|
|
117
143
|
if (opcodenum < Opcode.OP_PUSHDATA1) {
|
|
118
|
-
|
|
144
|
+
o += chunk.buf.copy(out, o)
|
|
119
145
|
} else if (opcodenum === Opcode.OP_PUSHDATA1) {
|
|
120
|
-
|
|
121
|
-
|
|
146
|
+
o = out.writeUInt8(chunk.len, o)
|
|
147
|
+
o += chunk.buf.copy(out, o)
|
|
122
148
|
} else if (opcodenum === Opcode.OP_PUSHDATA2) {
|
|
123
|
-
|
|
124
|
-
|
|
149
|
+
o = out.writeUInt16LE(chunk.len, o)
|
|
150
|
+
o += chunk.buf.copy(out, o)
|
|
125
151
|
} else if (opcodenum === Opcode.OP_PUSHDATA4) {
|
|
126
|
-
|
|
127
|
-
|
|
152
|
+
o = out.writeUInt32LE(chunk.len, o)
|
|
153
|
+
o += chunk.buf.copy(out, o)
|
|
128
154
|
}
|
|
129
155
|
}
|
|
130
156
|
}
|
|
157
|
+
return out
|
|
158
|
+
}
|
|
131
159
|
|
|
132
|
-
|
|
160
|
+
// A chunk's data must be a Buffer; BufferWriter#write asserted as much.
|
|
161
|
+
function bufLength (buf) {
|
|
162
|
+
if (!Buffer.isBuffer(buf)) throw new assert.AssertionError({ message: 'chunk data must be a Buffer', actual: buf, expected: 'Buffer', operator: 'isBuffer' })
|
|
163
|
+
return buf.length
|
|
133
164
|
}
|
|
134
165
|
|
|
135
166
|
Script.fromASM = function (str) {
|
|
@@ -1081,20 +1112,40 @@ Script.prototype.toAddress = function (network) {
|
|
|
1081
1112
|
*/
|
|
1082
1113
|
Script.prototype.findAndDelete = function (script) {
|
|
1083
1114
|
var buf = script.toBuffer()
|
|
1084
|
-
|
|
1115
|
+
// A chunk serializes to bytes starting with its opcode, so only chunks whose
|
|
1116
|
+
// opcode is the first byte of `buf` can match. Every other chunk is still
|
|
1117
|
+
// serialized when its encoding would throw, so malformed input fails as it
|
|
1118
|
+
// always did.
|
|
1119
|
+
var first = buf.length ? buf[0] : -1
|
|
1085
1120
|
for (var i = 0; i < this.chunks.length; i++) {
|
|
1086
|
-
var
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
if (
|
|
1121
|
+
var chunk = this.chunks[i]
|
|
1122
|
+
if (chunk.opcodenum !== first && serializesCleanly(chunk)) continue
|
|
1123
|
+
var buf2 = Script({
|
|
1124
|
+
chunks: [chunk]
|
|
1125
|
+
}).toBuffer()
|
|
1126
|
+
if (buf.equals(buf2)) {
|
|
1127
|
+
// Look at the chunk that slid into this position too: CScript::FindAndDelete
|
|
1128
|
+
// removes consecutive occurrences.
|
|
1092
1129
|
this.chunks.splice(i, 1)
|
|
1130
|
+
i--
|
|
1093
1131
|
}
|
|
1094
1132
|
}
|
|
1095
1133
|
return this
|
|
1096
1134
|
}
|
|
1097
1135
|
|
|
1136
|
+
function serializesCleanly (chunk) {
|
|
1137
|
+
var op = chunk.opcodenum
|
|
1138
|
+
if (typeof op !== 'number' || !Number.isInteger(op) || op < 0 || op > 255) return false
|
|
1139
|
+
if (!chunk.buf) return true
|
|
1140
|
+
if (op > Opcode.OP_PUSHDATA4) return true
|
|
1141
|
+
if (!Buffer.isBuffer(chunk.buf)) return false
|
|
1142
|
+
var len = chunk.len
|
|
1143
|
+
if (op === Opcode.OP_PUSHDATA1) return Number.isInteger(len) && len >= 0 && len <= 0xff
|
|
1144
|
+
if (op === Opcode.OP_PUSHDATA2) return Number.isInteger(len) && len >= 0 && len <= 0xffff
|
|
1145
|
+
if (op === Opcode.OP_PUSHDATA4) return Number.isInteger(len) && len >= 0 && len <= 0xffffffff
|
|
1146
|
+
return true
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1098
1149
|
/**
|
|
1099
1150
|
* Comes from bitcoind's script interpreter CheckMinimalPush function
|
|
1100
1151
|
* @returns {boolean} if the chunk {i} is the smallest way to push that particular data.
|
|
@@ -102,8 +102,9 @@ var sighashPreimageForForkId = function (transaction, sighashType, inputNumber,
|
|
|
102
102
|
writer.writeUInt32LE(input.outputIndex)
|
|
103
103
|
|
|
104
104
|
// scriptCode of the input (serialized as scripts inside CTxOuts)
|
|
105
|
-
|
|
106
|
-
writer.
|
|
105
|
+
var scriptCode = subscript.toBuffer()
|
|
106
|
+
writer.writeVarintNum(scriptCode.length)
|
|
107
|
+
writer.write(scriptCode)
|
|
107
108
|
|
|
108
109
|
// value of the output spent by this input (8-byte little endian)
|
|
109
110
|
writer.writeUInt64LEBN(satoshisBN)
|
|
@@ -148,8 +149,13 @@ var sighashPreimage = function sighashPreimage (transaction, sighashType, inputN
|
|
|
148
149
|
// Copy transaction
|
|
149
150
|
var txcopy = Transaction.shallowCopy(transaction)
|
|
150
151
|
|
|
151
|
-
//
|
|
152
|
-
|
|
152
|
+
// The BIP-143 path below only reads the script. The original algorithm
|
|
153
|
+
// modifies it, so it takes its own copy there; copying a large script up
|
|
154
|
+
// front cost more than the whole digest. Anything that is not a Script yet
|
|
155
|
+
// is converted, as the copy did.
|
|
156
|
+
if (!(subscript instanceof Script)) {
|
|
157
|
+
subscript = new Script(subscript)
|
|
158
|
+
}
|
|
153
159
|
|
|
154
160
|
if (flags & Interpreter.SCRIPT_ENABLE_REPLAY_PROTECTION) {
|
|
155
161
|
// Legacy chain's value for fork id must be of the form 0xffxxxx.
|
|
@@ -192,7 +198,8 @@ var sighashPreimage = function sighashPreimage (transaction, sighashType, inputN
|
|
|
192
198
|
return sighashPreimageForForkId(txcopy, sighashType, inputNumber, subscript, satoshisBN)
|
|
193
199
|
}
|
|
194
200
|
|
|
195
|
-
// For no ForkId sighash, separators need to be removed.
|
|
201
|
+
// For no ForkId sighash, separators need to be removed — from a copy.
|
|
202
|
+
subscript = new Script(subscript)
|
|
196
203
|
subscript.removeCodeseparators()
|
|
197
204
|
|
|
198
205
|
var i
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smartledger/bsv",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.11.0",
|
|
4
4
|
"description": "Bitcoin SV library with an interpreter-verified script engine: OP_PUSH_TX covenants, BIP-143 preimage tooling, and consensus flags that match what miners actually enforce. Also ships DID:web / W3C VC-JWT credentials and the Legal Token Protocol.",
|
|
5
5
|
"author": "SmartLedger Technology <hello@smartledger.technology> (https://smartledger.technology)",
|
|
6
6
|
"homepage": "https://github.com/codenlighten/smartledger-bsv#readme",
|
package/version.js
CHANGED