@smartledger/bsv 8.3.1 → 9.1.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 +228 -0
- package/README.md +152 -1031
- package/STABILITY.md +134 -0
- package/bsv-gdaf.min.js +58 -53
- package/bsv-ltp.min.js +23 -18
- package/bsv-script-helper.min.js +1 -1
- package/bsv-smartcontract.min.js +21 -21
- package/bsv.bundle.js +58 -53
- package/bsv.d.ts +0 -4
- package/bsv.min.js +58 -53
- package/docs/BRC220_BATCH_LEAF_AMENDMENT.md +82 -7
- package/docs/MODULE_REFERENCE_COMPLETE.md +27 -27
- package/docs/README.md +2 -1
- package/docs/THREAT_MODEL.md +10 -2
- package/docs/advanced/UTXO_MANAGER_GUIDE.md +1 -1
- 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/docs/proposals/10.0.0-package-split.md +131 -0
- package/index.js +15 -26
- package/lib/block/merkleblock.js +19 -5
- package/lib/covenant/helpers.js +34 -35
- package/lib/covenant/pushtx.js +2 -2
- package/lib/custom-script-helper.js +0 -16
- package/lib/hdprivatekey.js +15 -0
- package/lib/ordinals/ordlock.js +1 -1
- package/lib/script/interpreter.js +109 -1
- package/lib/smart_contract/builder.js +14 -0
- package/lib/smart_contract/debugger.js +2 -2
- package/lib/smart_contract/dsl.js +2 -2
- package/lib/smart_contract/index.js +0 -3
- package/lib/smart_contract/locks.js +1 -41
- package/lib/smart_contract/pels.js +1 -1
- package/lib/smart_contract/token.js +1 -1
- package/lib/util/deprecate.js +159 -0
- package/package.json +19 -82
- package/tools/gen-brc220-batch-vector.js +205 -0
- package/version.js +1 -1
- package/.mocharc.json +0 -5
- package/test/address.js +0 -629
- package/test/block/block.js +0 -239
- package/test/block/blockheader.js +0 -270
- package/test/block/merkleblock.js +0 -207
- package/test/build/bundle_crypto_shim.js +0 -104
- package/test/build/bundle_externals.js +0 -125
- package/test/build/bundle_smoke.js +0 -55
- package/test/build/esbuild_main.js +0 -65
- package/test/build/esm_wrapper.js +0 -73
- package/test/build/exports_resolution.js +0 -84
- package/test/build/version_sync.js +0 -14
- package/test/cli/smoke.js +0 -261
- package/test/consensus/base58-vectors.js +0 -120
- package/test/consensus/sv-script-vectors.js +0 -81
- package/test/consensus/sv-sighash-vectors.js +0 -51
- package/test/consensus/sv-tx-vectors.js +0 -48
- package/test/credentials-test.js +0 -332
- package/test/crypto/backend_selection.js +0 -126
- package/test/crypto/bn.js +0 -168
- package/test/crypto/ecdsa.js +0 -426
- package/test/crypto/elliptic-fixed.js +0 -61
- package/test/crypto/hash.browser.js +0 -121
- package/test/crypto/hash.js +0 -122
- package/test/crypto/point.js +0 -193
- package/test/crypto/random.js +0 -105
- package/test/crypto/security.js +0 -176
- package/test/crypto/shamir.js +0 -177
- package/test/crypto/shamir_rngcap.js +0 -29
- package/test/crypto/signature.js +0 -399
- package/test/data/bip69.json +0 -215
- package/test/data/bitcoin-sv/README.md +0 -170
- package/test/data/bitcoin-sv/base58_encode_decode.json +0 -14
- package/test/data/bitcoin-sv/base58_keys_invalid.json +0 -152
- package/test/data/bitcoin-sv/base58_keys_valid.json +0 -452
- package/test/data/bitcoin-sv/script_tests.json +0 -2591
- package/test/data/bitcoin-sv/sighash.json +0 -1003
- package/test/data/bitcoin-sv/tx_invalid.json +0 -285
- package/test/data/bitcoin-sv/tx_valid.json +0 -367
- package/test/data/bitcoind/base58_keys_invalid.json +0 -152
- package/test/data/bitcoind/base58_keys_valid.json +0 -452
- package/test/data/bitcoind/blocks.json +0 -27
- package/test/data/bitcoind/script_tests.json +0 -2244
- package/test/data/bitcoind/sig_canonical.json +0 -7
- package/test/data/bitcoind/sig_noncanonical.json +0 -22
- package/test/data/bitcoind/tx_invalid.json +0 -177
- package/test/data/bitcoind/tx_valid.json +0 -224
- package/test/data/blk86756-testnet.dat +0 -0
- package/test/data/blk86756-testnet.js +0 -12
- package/test/data/blk86756-testnet.json +0 -684
- package/test/data/ecdsa.json +0 -230
- package/test/data/merkleblocks.js +0 -486
- package/test/data/messages.json +0 -22
- package/test/data/sighash.json +0 -1004
- package/test/data/tx_creation.json +0 -85
- package/test/didweb/relationships.js +0 -144
- package/test/ecies/bitcore-ecies.js +0 -178
- package/test/ecies/electrum-ecies.js +0 -206
- package/test/encoding/base58.js +0 -131
- package/test/encoding/base58check.js +0 -145
- package/test/encoding/bufferreader.js +0 -328
- package/test/encoding/bufferwriter.js +0 -160
- package/test/encoding/varint.js +0 -104
- package/test/gdaf/anchor_no_key_leak.js +0 -146
- package/test/gdaf/anchor_spv.js +0 -163
- package/test/gdaf/canonicalization.js +0 -106
- package/test/gdaf/canonicalize.js +0 -140
- package/test/gdaf/zk_prover.js +0 -204
- package/test/hdkeys.js +0 -365
- package/test/hdprivatekey.js +0 -339
- package/test/hdpublickey.js +0 -293
- package/test/index.js +0 -16
- package/test/ltp/ids.js +0 -74
- package/test/ltp/right.js +0 -198
- package/test/ltp/verify_failclosed.js +0 -134
- package/test/message/message.js +0 -190
- package/test/mnemonic/data/fixtures.json +0 -300
- package/test/mnemonic/mnemonic.js +0 -277
- package/test/mnemonic/mocha.opts +0 -1
- package/test/mnemonic/pbkdf2.test.js +0 -43
- package/test/networks.js +0 -207
- package/test/notaryhash/batch_leaf.js +0 -140
- package/test/notaryhash/certificate.js +0 -249
- package/test/notaryhash/encoding.js +0 -186
- package/test/notaryhash/interop.js +0 -112
- package/test/notaryhash/merkle.js +0 -181
- package/test/notaryhash/script.js +0 -270
- package/test/notaryhash/verify.js +0 -342
- package/test/opcode.js +0 -186
- package/test/ordinals/bsv20.js +0 -337
- package/test/ordinals/inscription.js +0 -319
- package/test/ordinals/ordlock.js +0 -613
- package/test/privatekey.js +0 -540
- package/test/publickey.js +0 -411
- package/test/regressions.js +0 -215
- package/test/script/chronicle.js +0 -543
- package/test/script/defaults.js +0 -160
- package/test/script/genesis_limits.js +0 -203
- package/test/script/interpreter.js +0 -776
- package/test/script/script.js +0 -1259
- package/test/script/string_ops.js +0 -88
- package/test/security/fail_closed_contracts.js +0 -104
- package/test/security/threat_model_coverage.js +0 -31
- package/test/smart_contract/covenants.js +0 -245
- package/test/smart_contract/dsl_debugger.js +0 -101
- package/test/smart_contract/extract_field.js +0 -61
- package/test/smart_contract/nonenforcing_guard.js +0 -44
- package/test/smart_contract/ordinal_transfer.js +0 -81
- package/test/smart_contract/preimage.js +0 -98
- package/test/smart_contract/sighash_marketplace.js +0 -108
- package/test/smart_contract/token_generalized.js +0 -185
- package/test/spv/headerchain.js +0 -86
- package/test/spv/merkleproof.js +0 -133
- package/test/statuslist/failclosed.js +0 -78
- package/test/transaction/deserialize.js +0 -33
- package/test/transaction/input/input.js +0 -92
- package/test/transaction/input/multisig.js +0 -174
- package/test/transaction/input/multisigscripthash.js +0 -111
- package/test/transaction/input/publickey.js +0 -68
- package/test/transaction/input/publickeyhash.js +0 -59
- package/test/transaction/output.js +0 -185
- package/test/transaction/sighash.js +0 -91
- package/test/transaction/signature.js +0 -127
- package/test/transaction/transaction.js +0 -1299
- package/test/transaction/unspentoutput.js +0 -97
- package/test/types/dts_drift.js +0 -124
- package/test/types/surface_honesty.js +0 -102
- package/test/util/id.js +0 -72
- package/test/util/js.js +0 -76
- package/test/util/preconditions.js +0 -79
- package/test/vcjwt/interop.js +0 -126
|
@@ -1,319 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
/* global describe, it */
|
|
4
|
-
|
|
5
|
-
// 1Sat Ordinals inscription build/parse round-trip + output construction.
|
|
6
|
-
|
|
7
|
-
require('chai').should()
|
|
8
|
-
var bsv = require('../..')
|
|
9
|
-
var Ord = bsv.Ordinals
|
|
10
|
-
|
|
11
|
-
describe('Ordinals inscriptions', function () {
|
|
12
|
-
var key = bsv.PrivateKey.fromRandom()
|
|
13
|
-
var address = key.toAddress()
|
|
14
|
-
|
|
15
|
-
it('builds a P2PKH inscription and round-trips through parse', function () {
|
|
16
|
-
var s = Ord.buildInscription({
|
|
17
|
-
address: address, contentType: 'text/plain', content: 'hello ordinals'
|
|
18
|
-
})
|
|
19
|
-
var parsed = Ord.parseInscription(s)
|
|
20
|
-
parsed.should.be.an('object')
|
|
21
|
-
parsed.contentType.should.equal('text/plain')
|
|
22
|
-
parsed.contentText.should.equal('hello ordinals')
|
|
23
|
-
// The base lock is exactly the P2PKH for the address.
|
|
24
|
-
parsed.lock.toHex().should.equal(bsv.Script.buildPublicKeyHashOut(address).toHex())
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
it('preserves binary content and content-type exactly', function () {
|
|
28
|
-
var content = bsv.crypto.Random.getRandomBuffer(64)
|
|
29
|
-
var s = Ord.buildInscription({ address: address, contentType: 'image/png', content: content })
|
|
30
|
-
var parsed = Ord.parseInscription(s)
|
|
31
|
-
parsed.contentType.should.equal('image/png')
|
|
32
|
-
parsed.content.equals(content).should.equal(true)
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
it('round-trips through hex serialization', function () {
|
|
36
|
-
var s = Ord.buildInscription({ address: address, contentType: 'application/json', content: '{"a":1}' })
|
|
37
|
-
var parsed = Ord.parseInscription(s.toHex())
|
|
38
|
-
parsed.contentText.should.equal('{"a":1}')
|
|
39
|
-
parsed.contentType.should.equal('application/json')
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
it('accepts a custom base lock script', function () {
|
|
43
|
-
var lock = bsv.Script.buildPublicKeyHashOut(address)
|
|
44
|
-
var s = Ord.buildInscription({ lock: lock, contentType: 'text/plain', content: 'x' })
|
|
45
|
-
Ord.isInscription(s).should.equal(true)
|
|
46
|
-
Ord.parseInscription(s).lock.toHex().should.equal(lock.toHex())
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
it('isInscription is false for a plain P2PKH script', function () {
|
|
50
|
-
var p2pkh = bsv.Script.buildPublicKeyHashOut(address)
|
|
51
|
-
Ord.isInscription(p2pkh).should.equal(false)
|
|
52
|
-
var isNull = Ord.parseInscription(p2pkh) === null
|
|
53
|
-
isNull.should.equal(true)
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
it('createInscriptionOutput is a 1-sat output carrying the inscription', function () {
|
|
57
|
-
var out = Ord.createInscriptionOutput({ address: address, contentType: 'text/plain', content: 'hi' })
|
|
58
|
-
out.satoshis.should.equal(1)
|
|
59
|
-
Ord.isInscription(out.script).should.equal(true)
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
it('batchInscriptionOutputs builds one output per item', function () {
|
|
63
|
-
var outs = Ord.batchInscriptionOutputs([
|
|
64
|
-
{ address: address, contentType: 'text/plain', content: 'a' },
|
|
65
|
-
{ address: address, contentType: 'text/plain', content: 'b' }
|
|
66
|
-
])
|
|
67
|
-
outs.length.should.equal(2)
|
|
68
|
-
Ord.parseInscription(outs[0].script).contentText.should.equal('a')
|
|
69
|
-
Ord.parseInscription(outs[1].script).contentText.should.equal('b')
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
// The 1Sat spec allows the locking script to be prepended OR appended to the
|
|
73
|
-
// envelope. The parser only ever looked before it, so an appended lock was dropped
|
|
74
|
-
// and an owned ordinal was reported as carrying no locking script at all.
|
|
75
|
-
describe('recovers the lock wherever the spec allows it to sit', function () {
|
|
76
|
-
var p2pkh = bsv.Script.buildPublicKeyHashOut(address)
|
|
77
|
-
|
|
78
|
-
function concat () {
|
|
79
|
-
var out = new bsv.Script()
|
|
80
|
-
Array.prototype.slice.call(arguments).forEach(function (part) {
|
|
81
|
-
part.chunks.forEach(function (c) { out.chunks.push(c) })
|
|
82
|
-
})
|
|
83
|
-
return out
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function envelope () {
|
|
87
|
-
return Ord.buildInscription({
|
|
88
|
-
lock: new bsv.Script(), allowEmptyLock: true, contentType: 'text/plain', content: 'hello'
|
|
89
|
-
})
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
it('recovers a lock that precedes the envelope', function () {
|
|
93
|
-
var parsed = Ord.parseInscription(concat(p2pkh, envelope()))
|
|
94
|
-
parsed.lock.toHex().should.equal(p2pkh.toHex())
|
|
95
|
-
parsed.contentText.should.equal('hello')
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
it('recovers a lock that follows the envelope', function () {
|
|
99
|
-
var parsed = Ord.parseInscription(concat(envelope(), p2pkh))
|
|
100
|
-
parsed.lock.toHex().should.equal(p2pkh.toHex())
|
|
101
|
-
parsed.contentText.should.equal('hello')
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
it('keeps a separating OP_CODESEPARATOR, which really does run', function () {
|
|
105
|
-
var sep = concat(p2pkh, new bsv.Script().add(bsv.Opcode.OP_CODESEPARATOR), envelope())
|
|
106
|
-
var parsed = Ord.parseInscription(sep)
|
|
107
|
-
parsed.lock.chunks.length.should.equal(p2pkh.chunks.length + 1)
|
|
108
|
-
parsed.contentText.should.equal('hello')
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
it('still reports no lock when there genuinely is none', function () {
|
|
112
|
-
Ord.parseInscription(envelope()).lock.chunks.length.should.equal(0)
|
|
113
|
-
})
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
// Every case below used to succeed and emit a well-formed script that inscribed
|
|
117
|
-
// something other than what the caller asked for. An inscription is permanent, so
|
|
118
|
-
// each one now fails loudly at build time instead of on-chain.
|
|
119
|
-
describe('rejects arguments that would silently inscribe the wrong thing', function () {
|
|
120
|
-
it('throws when content is omitted rather than inscribing an empty payload', function () {
|
|
121
|
-
(function () {
|
|
122
|
-
Ord.buildInscription({ address: address, contentType: 'text/plain' })
|
|
123
|
-
}).should.throw(/requires `content`/)
|
|
124
|
-
})
|
|
125
|
-
|
|
126
|
-
it('names the field the caller actually passed', function () {
|
|
127
|
-
// The real-world report: a wallet whose own builder calls the field `data`.
|
|
128
|
-
(function () {
|
|
129
|
-
Ord.buildInscription({ address: address, contentType: 'text/plain', data: 'hello world' })
|
|
130
|
-
}).should.throw(/received `data`, which is not read/)
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
it('still allows an explicitly empty payload', function () {
|
|
134
|
-
var s = Ord.buildInscription({ address: address, contentType: 'text/plain', content: '' })
|
|
135
|
-
Ord.parseInscription(s).content.length.should.equal(0)
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
it('throws rather than stringifying an object into the payload', function () {
|
|
139
|
-
// String({}) is '[object Object]' — permanent, and never intended.
|
|
140
|
-
(function () {
|
|
141
|
-
Ord.buildInscription({ address: address, contentType: 'text/plain', content: { a: 1 } })
|
|
142
|
-
}).should.throw(/content must be a string or Buffer, got an object/)
|
|
143
|
-
})
|
|
144
|
-
|
|
145
|
-
it('throws on any non-string, non-Buffer content', function () {
|
|
146
|
-
[42, true, null, ['a'], undefined].forEach(function (v) {
|
|
147
|
-
(function () {
|
|
148
|
-
Ord.buildInscription({ address: address, contentType: 'text/plain', content: v })
|
|
149
|
-
}).should.throw(Error)
|
|
150
|
-
})
|
|
151
|
-
})
|
|
152
|
-
|
|
153
|
-
it('requires a contentType for Buffer content instead of labelling it text/plain', function () {
|
|
154
|
-
var png = Buffer.from([0x89, 0x50, 0x4e, 0x47])
|
|
155
|
-
;(function () {
|
|
156
|
-
Ord.buildInscription({ address: address, content: png })
|
|
157
|
-
}).should.throw(/contentType is required when content is a Buffer/)
|
|
158
|
-
// Declared explicitly, it builds.
|
|
159
|
-
var s = Ord.buildInscription({ address: address, contentType: 'image/png', content: png })
|
|
160
|
-
Ord.parseInscription(s).contentType.should.equal('image/png')
|
|
161
|
-
})
|
|
162
|
-
|
|
163
|
-
it('keeps the text/plain default for string content', function () {
|
|
164
|
-
var s = Ord.buildInscription({ address: address, content: 'hi' })
|
|
165
|
-
Ord.parseInscription(s).contentType.should.equal('text/plain')
|
|
166
|
-
})
|
|
167
|
-
|
|
168
|
-
it('throws on an empty or non-string contentType', function () {
|
|
169
|
-
(function () {
|
|
170
|
-
Ord.buildInscription({ address: address, contentType: '', content: 'x' })
|
|
171
|
-
}).should.throw(/contentType must not be empty/)
|
|
172
|
-
;(function () {
|
|
173
|
-
Ord.buildInscription({ address: address, contentType: {}, content: 'x' })
|
|
174
|
-
}).should.throw(/contentType must be a string or Buffer/)
|
|
175
|
-
})
|
|
176
|
-
|
|
177
|
-
it('throws on an empty base lock, which would be anyone-can-spend', function () {
|
|
178
|
-
// With no base lock the script is just the inert envelope: OP_FALSE OP_IF skips
|
|
179
|
-
// to OP_ENDIF, so whatever the spender pushed is the final stack and any spender
|
|
180
|
-
// succeeds. Proven below rather than asserted.
|
|
181
|
-
(function () {
|
|
182
|
-
Ord.buildInscription({ lock: Buffer.alloc(0), contentType: 'text/plain', content: 'x' })
|
|
183
|
-
}).should.throw(/spendable by anyone/)
|
|
184
|
-
})
|
|
185
|
-
|
|
186
|
-
it('proves the empty-lock script really is anyone-can-spend', function () {
|
|
187
|
-
var envelope = Ord.buildInscription({
|
|
188
|
-
lock: new bsv.Script(), allowEmptyLock: true, contentType: 'text/plain', content: 'x'
|
|
189
|
-
})
|
|
190
|
-
// An unlocking script from a key unrelated to `address` satisfies it.
|
|
191
|
-
var unlock = new bsv.Script().add(bsv.Opcode.OP_1)
|
|
192
|
-
var interp = new bsv.Script.Interpreter()
|
|
193
|
-
var ok = interp.verify(unlock, envelope, new bsv.Transaction(), 0, 0)
|
|
194
|
-
ok.should.equal(true)
|
|
195
|
-
})
|
|
196
|
-
|
|
197
|
-
it('permits an empty lock only when the caller opts in', function () {
|
|
198
|
-
var s = Ord.buildInscription({
|
|
199
|
-
lock: new bsv.Script(), allowEmptyLock: true, contentType: 'text/plain', content: 'x'
|
|
200
|
-
})
|
|
201
|
-
Ord.isInscription(s).should.equal(true)
|
|
202
|
-
})
|
|
203
|
-
|
|
204
|
-
it('throws when both lock and address are given instead of ignoring one', function () {
|
|
205
|
-
var lock = bsv.Script.buildPublicKeyHashOut(address)
|
|
206
|
-
var other = bsv.PrivateKey.fromRandom().toAddress()
|
|
207
|
-
;(function () {
|
|
208
|
-
Ord.buildInscription({ lock: lock, address: other, contentType: 'text/plain', content: 'x' })
|
|
209
|
-
}).should.throw(/not both/)
|
|
210
|
-
})
|
|
211
|
-
|
|
212
|
-
it('rejects a satoshi amount that carries no ordinal', function () {
|
|
213
|
-
[0, '1', 1.5, -1].forEach(function (v) {
|
|
214
|
-
(function () {
|
|
215
|
-
Ord.createInscriptionOutput({
|
|
216
|
-
address: address, contentType: 'text/plain', content: 'x', satoshis: v
|
|
217
|
-
})
|
|
218
|
-
}).should.throw(Error)
|
|
219
|
-
})
|
|
220
|
-
Ord.createInscriptionOutput({
|
|
221
|
-
address: address, contentType: 'text/plain', content: 'x'
|
|
222
|
-
}).satoshis.should.equal(1)
|
|
223
|
-
})
|
|
224
|
-
})
|
|
225
|
-
|
|
226
|
-
// The case that motivated making the script-size cap configurable: transferring a
|
|
227
|
-
// large inscription. The envelope is inert, so the spend is an ordinary P2PKH — but
|
|
228
|
-
// the interpreter could not even load the script, because total script size was a
|
|
229
|
-
// hard-coded 10,000 bytes that useGenesisLimits() did not lift.
|
|
230
|
-
describe('transferring a large inscription', function () {
|
|
231
|
-
var I = bsv.Script.Interpreter
|
|
232
|
-
var Sighash = bsv.Transaction.Sighash
|
|
233
|
-
var BN = bsv.crypto.BN
|
|
234
|
-
var SIGHASH = bsv.crypto.Signature.SIGHASH_ALL | bsv.crypto.Signature.SIGHASH_FORKID
|
|
235
|
-
var FLAGS = I.SCRIPT_VERIFY_STRICTENC | I.SCRIPT_ENABLE_SIGHASH_FORKID
|
|
236
|
-
var saved
|
|
237
|
-
|
|
238
|
-
beforeEach(function () { saved = I.getLimits() })
|
|
239
|
-
afterEach(function () { I.setLimits(saved) })
|
|
240
|
-
|
|
241
|
-
// A signed transfer of a `kb`-sized inscription to a new owner.
|
|
242
|
-
function transfer (kb) {
|
|
243
|
-
var owner = bsv.PrivateKey.fromBuffer(Buffer.alloc(32, 11))
|
|
244
|
-
var recipient = bsv.PrivateKey.fromBuffer(Buffer.alloc(32, 22))
|
|
245
|
-
var lock = Ord.buildInscription({
|
|
246
|
-
address: owner.toAddress(),
|
|
247
|
-
contentType: 'image/png',
|
|
248
|
-
content: bsv.crypto.Random.getRandomBuffer(kb * 1024)
|
|
249
|
-
})
|
|
250
|
-
var spend = new bsv.Transaction()
|
|
251
|
-
spend.addInput(new bsv.Transaction.Input({
|
|
252
|
-
prevTxId: 'aa'.repeat(32), outputIndex: 0, script: bsv.Script.empty()
|
|
253
|
-
}), lock, 1)
|
|
254
|
-
spend.addOutput(new bsv.Transaction.Output({
|
|
255
|
-
script: bsv.Script.buildPublicKeyHashOut(recipient.toAddress()), satoshis: 1
|
|
256
|
-
}))
|
|
257
|
-
// Sign over the FULL previous locking script — envelope included. That is the
|
|
258
|
-
// script code the network uses; signing the base lock alone yields a signature
|
|
259
|
-
// that verifies against its own preimage and nothing else.
|
|
260
|
-
var sig = Sighash.sign(spend, owner, SIGHASH, 0, lock, new BN(1), FLAGS)
|
|
261
|
-
var unlock = new bsv.Script()
|
|
262
|
-
.add(Buffer.concat([sig.toDER(), Buffer.from([SIGHASH])]))
|
|
263
|
-
.add(owner.toPublicKey().toBuffer())
|
|
264
|
-
spend.inputs[0].setScript(unlock)
|
|
265
|
-
return { lock: lock, unlock: unlock, spend: spend, sig: sig, owner: owner }
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
function evaluate (t) {
|
|
269
|
-
var interp = new I()
|
|
270
|
-
var ok = interp.verify(t.unlock, t.lock, t.spend, 0, FLAGS, new BN(1))
|
|
271
|
-
return { ok: ok, err: interp.errstr }
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
it('cannot be evaluated under pre-Genesis limits — two separate caps bite', function () {
|
|
275
|
-
// Under 10 KB the script loads and the 520-byte push cap rejects the content...
|
|
276
|
-
var small = evaluate(transfer(3))
|
|
277
|
-
small.ok.should.equal(false)
|
|
278
|
-
small.err.should.equal('SCRIPT_ERR_PUSH_SIZE')
|
|
279
|
-
// ...over 10 KB it never gets that far: evaluate() refuses the script outright.
|
|
280
|
-
// This is the cap useGenesisLimits() could not lift.
|
|
281
|
-
var big = evaluate(transfer(50))
|
|
282
|
-
big.ok.should.equal(false)
|
|
283
|
-
big.err.should.equal('SCRIPT_ERR_SCRIPT_SIZE')
|
|
284
|
-
})
|
|
285
|
-
|
|
286
|
-
it('evaluates once Genesis limits are enabled', function () {
|
|
287
|
-
bsv.SmartContract.enableGenesis()
|
|
288
|
-
var t = transfer(50)
|
|
289
|
-
t.lock.toBuffer().length.should.be.above(10000) // past the old hard-coded cap
|
|
290
|
-
evaluate(t).ok.should.equal(true)
|
|
291
|
-
})
|
|
292
|
-
|
|
293
|
-
it('agrees with a direct signature check against the sighash', function () {
|
|
294
|
-
// The fallback used when the interpreter cannot run: verify the signature over
|
|
295
|
-
// the sighash directly. It must agree with the interpreter where both work.
|
|
296
|
-
bsv.SmartContract.enableGenesis()
|
|
297
|
-
var t = transfer(50)
|
|
298
|
-
var hash = Sighash.sighash(t.spend, SIGHASH, 0, t.lock, new BN(1), FLAGS)
|
|
299
|
-
var sigOk = bsv.crypto.ECDSA.verify(hash, t.sig, t.owner.toPublicKey(), 'little')
|
|
300
|
-
sigOk.should.equal(true)
|
|
301
|
-
evaluate(t).ok.should.equal(true)
|
|
302
|
-
})
|
|
303
|
-
|
|
304
|
-
it('rejects a signature made over the base lock instead of the full script', function () {
|
|
305
|
-
bsv.SmartContract.enableGenesis()
|
|
306
|
-
var t = transfer(50)
|
|
307
|
-
var baseLock = bsv.Script.buildPublicKeyHashOut(t.owner.toAddress())
|
|
308
|
-
var wrong = Sighash.sign(t.spend, t.owner, SIGHASH, 0, baseLock, new BN(1), FLAGS)
|
|
309
|
-
var hash = Sighash.sighash(t.spend, SIGHASH, 0, t.lock, new BN(1), FLAGS)
|
|
310
|
-
// Verifies against its own (wrong) preimage, but not the one the network checks.
|
|
311
|
-
bsv.crypto.ECDSA.verify(hash, wrong, t.owner.toPublicKey(), 'little').should.equal(false)
|
|
312
|
-
t.spend.inputs[0].setScript(new bsv.Script()
|
|
313
|
-
.add(Buffer.concat([wrong.toDER(), Buffer.from([SIGHASH])]))
|
|
314
|
-
.add(t.owner.toPublicKey().toBuffer()))
|
|
315
|
-
var interp = new I()
|
|
316
|
-
interp.verify(t.spend.inputs[0].script, t.lock, t.spend, 0, FLAGS, new BN(1)).should.equal(false)
|
|
317
|
-
})
|
|
318
|
-
})
|
|
319
|
-
})
|