@smartledger/bsv 9.3.0 → 9.5.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 +105 -0
- package/README.md +19 -19
- package/bsv-gdaf.min.js +52 -52
- package/bsv-ltp.min.js +1 -1
- package/bsv-smartcontract.min.js +18 -18
- package/bsv.bundle.js +52 -52
- package/bsv.d.ts +8 -0
- package/bsv.min.js +52 -52
- package/docs/AUDIT_SCOPE.md +135 -34
- package/docs/MODULE_REFERENCE_COMPLETE.md +27 -27
- 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/lib/script/interpreter.js +34 -5
- package/lib/smart_contract/dsl.js +55 -3
- package/package.json +3 -3
- package/version.js +1 -1
|
@@ -28,6 +28,11 @@ var Opcode = require('../opcode')
|
|
|
28
28
|
var Transaction = require('../transaction')
|
|
29
29
|
var n = helpers.scriptNum
|
|
30
30
|
|
|
31
|
+
// Consensus constants, named so the compiled script can be read against the node.
|
|
32
|
+
var LOCKTIME_THRESHOLD = 500000000 // below: block height. at or above: unix time.
|
|
33
|
+
var SEQUENCE_FINAL = Buffer.from([0xff, 0xff, 0xff, 0xff])
|
|
34
|
+
var SIGN_PAD = Buffer.from([0x00]) // makes an unsigned 32-bit field read positive
|
|
35
|
+
|
|
31
36
|
function toOutput (dest, satoshis) {
|
|
32
37
|
if (dest instanceof Transaction.Output) return dest
|
|
33
38
|
if (dest instanceof Script) return new Transaction.Output({ script: dest, satoshis: satoshis })
|
|
@@ -59,8 +64,22 @@ Policy.prototype.payTo = function (dest, satoshis) {
|
|
|
59
64
|
return this
|
|
60
65
|
}
|
|
61
66
|
|
|
62
|
-
/**
|
|
67
|
+
/**
|
|
68
|
+
* Require the spend's nLockTime to be >= height.
|
|
69
|
+
*
|
|
70
|
+
* Below LOCKTIME_THRESHOLD (500000000) the value is a BLOCK HEIGHT; at or above
|
|
71
|
+
* it, a UNIX TIMESTAMP. The compiled script enforces the same unit the floor
|
|
72
|
+
* uses, so a height floor cannot be satisfied by a timestamp.
|
|
73
|
+
*
|
|
74
|
+
* 0 is rejected: consensus reads nLockTime 0 as "no lock" and treats the
|
|
75
|
+
* transaction as final regardless of any input's sequence, so a floor of 0
|
|
76
|
+
* would compile to a lock that binds nothing.
|
|
77
|
+
*/
|
|
63
78
|
Policy.prototype.lockUntil = function (height) {
|
|
79
|
+
if (!Number.isInteger(height) || height < 1 || height > 0xffffffff) {
|
|
80
|
+
throw new Error('lockUntil: expected an integer in 1..4294967295, got ' + height +
|
|
81
|
+
' (nLockTime 0 means "no lock" — consensus treats such a transaction as final)')
|
|
82
|
+
}
|
|
64
83
|
this._minLockTime = height
|
|
65
84
|
return this
|
|
66
85
|
}
|
|
@@ -75,7 +94,11 @@ Policy.prototype.describe = function () {
|
|
|
75
94
|
this._outputs.forEach(function (o, i) {
|
|
76
95
|
parts.push('output[' + i + '] = ' + o.satoshis + ' sat to ' + o.script.toASM().slice(0, 24) + '...')
|
|
77
96
|
})
|
|
78
|
-
if (this._minLockTime !== null)
|
|
97
|
+
if (this._minLockTime !== null) {
|
|
98
|
+
var unit = this._minLockTime < LOCKTIME_THRESHOLD ? 'block height' : 'unix time'
|
|
99
|
+
parts.push('nLockTime >= ' + this._minLockTime + ' as a ' + unit)
|
|
100
|
+
parts.push('this input is non-final (nSequence != 0xffffffff)')
|
|
101
|
+
}
|
|
79
102
|
return 'spend allowed iff: ' + parts.join(' AND ')
|
|
80
103
|
}
|
|
81
104
|
|
|
@@ -97,9 +120,38 @@ Policy.prototype.compile = function () {
|
|
|
97
120
|
}
|
|
98
121
|
|
|
99
122
|
if (this._minLockTime !== null) {
|
|
123
|
+
// A time lock is three consensus rules, not one comparison. All three are in
|
|
124
|
+
// the node's CheckLockTime; checking only the number reproduces none of them.
|
|
125
|
+
|
|
126
|
+
// 1. nSequence of THIS input must be non-final. IsFinalTx() ignores nLockTime
|
|
127
|
+
// outright when every input is 0xffffffff, so without this the spend is
|
|
128
|
+
// minable in the next block no matter how large a locktime it declares.
|
|
129
|
+
// One non-final input is enough to make the whole transaction non-final,
|
|
130
|
+
// and this input is the only one the preimage lets us see.
|
|
131
|
+
s.add(Opcode.OP_DUP)
|
|
132
|
+
s.add(n(44)).add(Opcode.OP_RIGHT).add(n(4)).add(Opcode.OP_LEFT) // last 44, first 4 = nSequence
|
|
133
|
+
s.add(SEQUENCE_FINAL).add(Opcode.OP_EQUAL).add(Opcode.OP_NOT).add(Opcode.OP_VERIFY)
|
|
134
|
+
|
|
135
|
+
// 2. nLockTime is an UNSIGNED 32-bit field, and OP_BIN2NUM reads a SIGNED
|
|
136
|
+
// one. From 19 Jan 2038 the high bit is set, and 0x80000000 minimally
|
|
137
|
+
// encodes to negative zero — the floor would be compared against 0 and no
|
|
138
|
+
// spend would ever satisfy it. Sign-pad to five bytes first. That push is
|
|
139
|
+
// only legal because OP_BIN2NUM now honours the era's script-number width.
|
|
100
140
|
s.add(Opcode.OP_DUP)
|
|
101
141
|
s.add(n(8)).add(Opcode.OP_RIGHT).add(n(4)).add(Opcode.OP_LEFT) // last 8, first 4 = nLockTime
|
|
102
|
-
s.add(
|
|
142
|
+
s.add(SIGN_PAD).add(Opcode.OP_CAT).add(Opcode.OP_BIN2NUM)
|
|
143
|
+
|
|
144
|
+
// 3. Units must match the floor's. Consensus reads nLockTime below
|
|
145
|
+
// LOCKTIME_THRESHOLD as a height and at or above it as a timestamp, so a
|
|
146
|
+
// bare `>=` lets a long-past timestamp clear a future height floor —
|
|
147
|
+
// 1500000000 >= 900000 is true, and that transaction is minable today.
|
|
148
|
+
// A floor already at or above the threshold needs no guard: `>= floor`
|
|
149
|
+
// implies `>= threshold`.
|
|
150
|
+
if (this._minLockTime < LOCKTIME_THRESHOLD) {
|
|
151
|
+
s.add(Opcode.OP_DUP).add(n(LOCKTIME_THRESHOLD)).add(Opcode.OP_LESSTHAN).add(Opcode.OP_VERIFY)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
s.add(n(this._minLockTime)).add(Opcode.OP_GREATERTHANOREQUAL).add(Opcode.OP_VERIFY)
|
|
103
155
|
}
|
|
104
156
|
|
|
105
157
|
s.add(Opcode.OP_DROP).add(Opcode.OP_1) // drop preimage; succeed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smartledger/bsv",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.5.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",
|
|
@@ -118,7 +118,7 @@
|
|
|
118
118
|
"test:all": "npm test && npm run test:covenants && npm run test:scripts",
|
|
119
119
|
"coverage": "nyc --reporter=text npm run test",
|
|
120
120
|
"demo": "node demos/smart_contract_demo.js",
|
|
121
|
-
"demo:web": "echo '
|
|
121
|
+
"demo:web": "echo '🌐 Open demos/smart_contract_demo.html in your browser'",
|
|
122
122
|
"demo:basics": "node demos/smart_contract_demo.js --feature basics",
|
|
123
123
|
"demo:covenant": "node demos/smart_contract_demo.js --feature covenant",
|
|
124
124
|
"demo:preimage": "node demos/smart_contract_demo.js --feature preimage",
|
|
@@ -127,7 +127,7 @@
|
|
|
127
127
|
"demo:legacy": "npm run test:covenants",
|
|
128
128
|
"demo:legacy:basic": "npm run test:basic",
|
|
129
129
|
"demo:legacy:scripts": "npm run test:scripts",
|
|
130
|
-
"demo:legacy:preimage": "echo '
|
|
130
|
+
"demo:legacy:preimage": "echo '🧠 BIP-143 Preimage Extractor Demo' && node examples/preimage/extract_preimage_bidirectional.js",
|
|
131
131
|
"smart-contracts": "node examples/smart_contract_templates.js",
|
|
132
132
|
"smart-contracts:working": "node examples/final_working_contracts.js",
|
|
133
133
|
"workflow": "node examples/complete_workflow_demo.js",
|
package/version.js
CHANGED