metered-protocol 1.0.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/LICENSE +21 -0
- package/README.md +103 -0
- package/contracts/metered.ag +135 -0
- package/contracts/metered_ag.tests.json +1226 -0
- package/contracts/metered_session.sil +237 -0
- package/contracts/metered_session.tests.json +1113 -0
- package/dist/contracts/metered.ag +135 -0
- package/dist/contracts/metered_ag.tests.json +1226 -0
- package/dist/contracts/metered_session.sil +237 -0
- package/dist/contracts/metered_session.tests.json +1113 -0
- package/dist/src/bias.d.ts +48 -0
- package/dist/src/bias.d.ts.map +1 -0
- package/dist/src/bias.js +43 -0
- package/dist/src/bias.js.map +1 -0
- package/dist/src/checkpoint.d.ts +57 -0
- package/dist/src/checkpoint.d.ts.map +1 -0
- package/dist/src/checkpoint.js +84 -0
- package/dist/src/checkpoint.js.map +1 -0
- package/dist/src/deadline.d.ts +71 -0
- package/dist/src/deadline.d.ts.map +1 -0
- package/dist/src/deadline.js +77 -0
- package/dist/src/deadline.js.map +1 -0
- package/dist/src/encoding.d.ts +72 -0
- package/dist/src/encoding.d.ts.map +1 -0
- package/dist/src/encoding.js +187 -0
- package/dist/src/encoding.js.map +1 -0
- package/dist/src/history.d.ts +33 -0
- package/dist/src/history.d.ts.map +1 -0
- package/dist/src/history.js +38 -0
- package/dist/src/history.js.map +1 -0
- package/dist/src/http/buyer.d.ts +57 -0
- package/dist/src/http/buyer.d.ts.map +1 -0
- package/dist/src/http/buyer.js +151 -0
- package/dist/src/http/buyer.js.map +1 -0
- package/dist/src/http/client.d.ts +55 -0
- package/dist/src/http/client.d.ts.map +1 -0
- package/dist/src/http/client.js +83 -0
- package/dist/src/http/client.js.map +1 -0
- package/dist/src/http/harness.d.ts +18 -0
- package/dist/src/http/harness.d.ts.map +1 -0
- package/dist/src/http/harness.js +16 -0
- package/dist/src/http/harness.js.map +1 -0
- package/dist/src/http/protocol.d.ts +84 -0
- package/dist/src/http/protocol.d.ts.map +1 -0
- package/dist/src/http/protocol.js +22 -0
- package/dist/src/http/protocol.js.map +1 -0
- package/dist/src/http/provider.d.ts +123 -0
- package/dist/src/http/provider.d.ts.map +1 -0
- package/dist/src/http/provider.js +197 -0
- package/dist/src/http/provider.js.map +1 -0
- package/dist/src/http/serve.d.ts +34 -0
- package/dist/src/http/serve.d.ts.map +1 -0
- package/dist/src/http/serve.js +171 -0
- package/dist/src/http/serve.js.map +1 -0
- package/dist/src/http/service.d.ts +86 -0
- package/dist/src/http/service.d.ts.map +1 -0
- package/dist/src/http/service.js +161 -0
- package/dist/src/http/service.js.map +1 -0
- package/dist/src/index.d.ts +68 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +62 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/meter.d.ts +39 -0
- package/dist/src/meter.d.ts.map +1 -0
- package/dist/src/meter.js +100 -0
- package/dist/src/meter.js.map +1 -0
- package/dist/src/offer.d.ts +6 -0
- package/dist/src/offer.d.ts.map +1 -0
- package/dist/src/offer.js +92 -0
- package/dist/src/offer.js.map +1 -0
- package/dist/src/reconcile.d.ts +18 -0
- package/dist/src/reconcile.d.ts.map +1 -0
- package/dist/src/reconcile.js +101 -0
- package/dist/src/reconcile.js.map +1 -0
- package/dist/src/reservation.d.ts +51 -0
- package/dist/src/reservation.d.ts.map +1 -0
- package/dist/src/reservation.js +124 -0
- package/dist/src/reservation.js.map +1 -0
- package/dist/src/session.d.ts +40 -0
- package/dist/src/session.d.ts.map +1 -0
- package/dist/src/session.js +92 -0
- package/dist/src/session.js.map +1 -0
- package/dist/src/signer.d.ts +31 -0
- package/dist/src/signer.d.ts.map +1 -0
- package/dist/src/signer.js +57 -0
- package/dist/src/signer.js.map +1 -0
- package/dist/src/store.d.ts +30 -0
- package/dist/src/store.d.ts.map +1 -0
- package/dist/src/store.js +120 -0
- package/dist/src/store.js.map +1 -0
- package/dist/src/types.d.ts +80 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +9 -0
- package/dist/src/types.js.map +1 -0
- package/dist/tools/anchor-cli.d.ts +2 -0
- package/dist/tools/anchor-cli.d.ts.map +1 -0
- package/dist/tools/anchor-cli.js +101 -0
- package/dist/tools/anchor-cli.js.map +1 -0
- package/dist/tools/anchor.d.ts +68 -0
- package/dist/tools/anchor.d.ts.map +1 -0
- package/dist/tools/anchor.js +136 -0
- package/dist/tools/anchor.js.map +1 -0
- package/dist/tools/chain.d.ts +18 -0
- package/dist/tools/chain.d.ts.map +1 -0
- package/dist/tools/chain.js +18 -0
- package/dist/tools/chain.js.map +1 -0
- package/dist/tools/conformance.d.ts +2 -0
- package/dist/tools/conformance.d.ts.map +1 -0
- package/dist/tools/conformance.js +220 -0
- package/dist/tools/conformance.js.map +1 -0
- package/dist/tools/contracts.d.ts +2 -0
- package/dist/tools/contracts.d.ts.map +1 -0
- package/dist/tools/contracts.js +68 -0
- package/dist/tools/contracts.js.map +1 -0
- package/dist/tools/covenant-binding.d.ts +40 -0
- package/dist/tools/covenant-binding.d.ts.map +1 -0
- package/dist/tools/covenant-binding.js +60 -0
- package/dist/tools/covenant-binding.js.map +1 -0
- package/dist/tools/covenant-profile.d.ts +41 -0
- package/dist/tools/covenant-profile.d.ts.map +1 -0
- package/dist/tools/covenant-profile.js +74 -0
- package/dist/tools/covenant-profile.js.map +1 -0
- package/dist/tools/covenant.d.ts +30 -0
- package/dist/tools/covenant.d.ts.map +1 -0
- package/dist/tools/covenant.js +54 -0
- package/dist/tools/covenant.js.map +1 -0
- package/dist/tools/demo-report.d.ts +24 -0
- package/dist/tools/demo-report.d.ts.map +1 -0
- package/dist/tools/demo-report.js +40 -0
- package/dist/tools/demo-report.js.map +1 -0
- package/dist/tools/demo.d.ts +2 -0
- package/dist/tools/demo.d.ts.map +1 -0
- package/dist/tools/demo.js +204 -0
- package/dist/tools/demo.js.map +1 -0
- package/dist/tools/dust-map.d.ts +2 -0
- package/dist/tools/dust-map.d.ts.map +1 -0
- package/dist/tools/dust-map.js +63 -0
- package/dist/tools/dust-map.js.map +1 -0
- package/dist/tools/expire-cases.d.ts +4 -0
- package/dist/tools/expire-cases.d.ts.map +1 -0
- package/dist/tools/expire-cases.js +211 -0
- package/dist/tools/expire-cases.js.map +1 -0
- package/dist/tools/fee-check.d.ts +2 -0
- package/dist/tools/fee-check.d.ts.map +1 -0
- package/dist/tools/fee-check.js +127 -0
- package/dist/tools/fee-check.js.map +1 -0
- package/dist/tools/fixtures.d.ts +39 -0
- package/dist/tools/fixtures.d.ts.map +1 -0
- package/dist/tools/fixtures.js +31 -0
- package/dist/tools/fixtures.js.map +1 -0
- package/dist/tools/gen-contract-tests.d.ts +2 -0
- package/dist/tools/gen-contract-tests.d.ts.map +1 -0
- package/dist/tools/gen-contract-tests.js +170 -0
- package/dist/tools/gen-contract-tests.js.map +1 -0
- package/dist/tools/kaspa.d.ts +13 -0
- package/dist/tools/kaspa.d.ts.map +1 -0
- package/dist/tools/kaspa.js +76 -0
- package/dist/tools/kaspa.js.map +1 -0
- package/dist/tools/live-deadline.d.ts +2 -0
- package/dist/tools/live-deadline.d.ts.map +1 -0
- package/dist/tools/live-deadline.js +122 -0
- package/dist/tools/live-deadline.js.map +1 -0
- package/dist/tools/live-expire.d.ts +2 -0
- package/dist/tools/live-expire.d.ts.map +1 -0
- package/dist/tools/live-expire.js +127 -0
- package/dist/tools/live-expire.js.map +1 -0
- package/dist/tools/live-settle.d.ts +2 -0
- package/dist/tools/live-settle.d.ts.map +1 -0
- package/dist/tools/live-settle.js +226 -0
- package/dist/tools/live-settle.js.map +1 -0
- package/dist/tools/live-steps.d.ts +63 -0
- package/dist/tools/live-steps.d.ts.map +1 -0
- package/dist/tools/live-steps.js +155 -0
- package/dist/tools/live-steps.js.map +1 -0
- package/dist/tools/model.d.ts +32 -0
- package/dist/tools/model.d.ts.map +1 -0
- package/dist/tools/model.js +99 -0
- package/dist/tools/model.js.map +1 -0
- package/dist/tools/send.d.ts +2 -0
- package/dist/tools/send.d.ts.map +1 -0
- package/dist/tools/send.js +41 -0
- package/dist/tools/send.js.map +1 -0
- package/dist/tools/session-chain.d.ts +69 -0
- package/dist/tools/session-chain.d.ts.map +1 -0
- package/dist/tools/session-chain.js +113 -0
- package/dist/tools/session-chain.js.map +1 -0
- package/dist/tools/sighash.d.ts +9 -0
- package/dist/tools/sighash.d.ts.map +1 -0
- package/dist/tools/sighash.js +68 -0
- package/dist/tools/sighash.js.map +1 -0
- package/dist/tools/sigscript-check.d.ts +2 -0
- package/dist/tools/sigscript-check.d.ts.map +1 -0
- package/dist/tools/sigscript-check.js +113 -0
- package/dist/tools/sigscript-check.js.map +1 -0
- package/dist/tools/sigscript.d.ts +61 -0
- package/dist/tools/sigscript.d.ts.map +1 -0
- package/dist/tools/sigscript.js +70 -0
- package/dist/tools/sigscript.js.map +1 -0
- package/dist/tools/state-layout.d.ts +2 -0
- package/dist/tools/state-layout.d.ts.map +1 -0
- package/dist/tools/state-layout.js +57 -0
- package/dist/tools/state-layout.js.map +1 -0
- package/package.json +59 -0
- package/spec/CONFORMANCE.md +80 -0
- package/spec/SPEC.md +821 -0
- package/spec/conformance-vectors.json +677 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `expire` cases -- the payout path, and the one that carries every bug found in this covenant.
|
|
3
|
+
*
|
|
4
|
+
* Every case here needs a real transaction signature, so each is built twice: once with a
|
|
5
|
+
* placeholder to learn the sighash, once with the signature over it. See tools/sighash.ts.
|
|
6
|
+
*/
|
|
7
|
+
import { sighashFor, signSighash } from './sighash.js';
|
|
8
|
+
import { BUYER_PK, BUYER_SK, PROVIDER_PK, PROVIDER_SK, STRANGER_SK, FUNDED, FEE, WINDOW, ctor, x } from './fixtures.js';
|
|
9
|
+
const PLACEHOLDER = x('44'.repeat(65));
|
|
10
|
+
const CLAIM = 4_000_000;
|
|
11
|
+
/** An expire spends the covenant and pays out. `sequence` is what satisfies the relative window. */
|
|
12
|
+
function expireTx(pendingSeq, pendingSompi, outputs, sequence = WINDOW) {
|
|
13
|
+
return {
|
|
14
|
+
active_input_index: 0,
|
|
15
|
+
inputs: [{ utxo_value: FUNDED, sequence, constructor_args: ctor(pendingSeq, pendingSompi) }],
|
|
16
|
+
outputs,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
const toBuyer = (value) => ({ value, p2pk_pubkey: x(BUYER_PK) });
|
|
20
|
+
const toProvider = (value) => ({ value, p2pk_pubkey: x(PROVIDER_PK) });
|
|
21
|
+
/** Each case, with the key that must sign it. The signature is filled in afterwards. */
|
|
22
|
+
const PLAN = [
|
|
23
|
+
{
|
|
24
|
+
signer: BUYER_SK,
|
|
25
|
+
case: {
|
|
26
|
+
name: 'BUG 1, THE STUCK FUNDS: nobody ever settled, so the buyer takes everything back',
|
|
27
|
+
function: 'expire',
|
|
28
|
+
constructor_args: ctor(-1, 0),
|
|
29
|
+
args: [x(BUYER_PK), x(PROVIDER_PK), PLACEHOLDER],
|
|
30
|
+
expect: 'pass',
|
|
31
|
+
tx: expireTx(-1, 0, [toBuyer(FUNDED - FEE)]),
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
signer: BUYER_SK,
|
|
36
|
+
case: {
|
|
37
|
+
name: 'BUG 1: with no claim, paying the provider instead of refunding the buyer is refused',
|
|
38
|
+
function: 'expire',
|
|
39
|
+
constructor_args: ctor(-1, 0),
|
|
40
|
+
args: [x(BUYER_PK), x(PROVIDER_PK), PLACEHOLDER],
|
|
41
|
+
expect: 'fail',
|
|
42
|
+
tx: expireTx(-1, 0, [toProvider(FUNDED - FEE)]),
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
signer: PROVIDER_SK,
|
|
47
|
+
case: {
|
|
48
|
+
name: 'the normal payout: the provider takes the claim, the buyer takes the remainder',
|
|
49
|
+
function: 'expire',
|
|
50
|
+
constructor_args: ctor(3, CLAIM),
|
|
51
|
+
args: [x(BUYER_PK), x(PROVIDER_PK), PLACEHOLDER],
|
|
52
|
+
expect: 'pass',
|
|
53
|
+
tx: expireTx(3, CLAIM, [toProvider(CLAIM), toBuyer(FUNDED - CLAIM - FEE)]),
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
signer: PROVIDER_SK,
|
|
58
|
+
case: {
|
|
59
|
+
name: 'BUG 2, THE BURNED REFUND: paying the buyer a token amount and burning the rest to fee is refused',
|
|
60
|
+
function: 'expire',
|
|
61
|
+
constructor_args: ctor(3, CLAIM),
|
|
62
|
+
args: [x(BUYER_PK), x(PROVIDER_PK), PLACEHOLDER],
|
|
63
|
+
expect: 'fail',
|
|
64
|
+
tx: expireTx(3, CLAIM, [toProvider(CLAIM), toBuyer(1)]),
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
signer: PROVIDER_SK,
|
|
69
|
+
case: {
|
|
70
|
+
name: 'THE OVERCLAIM: paying the provider more than the pending claim is refused',
|
|
71
|
+
function: 'expire',
|
|
72
|
+
constructor_args: ctor(3, CLAIM),
|
|
73
|
+
args: [x(BUYER_PK), x(PROVIDER_PK), PLACEHOLDER],
|
|
74
|
+
expect: 'fail',
|
|
75
|
+
tx: expireTx(3, CLAIM, [toProvider(CLAIM + 1_000_000), toBuyer(FUNDED - CLAIM - 1_000_000 - FEE)]),
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
signer: PROVIDER_SK,
|
|
80
|
+
case: {
|
|
81
|
+
name: 'THE WRONG DESTINATION: paying the claim to a stranger instead of the provider is refused',
|
|
82
|
+
function: 'expire',
|
|
83
|
+
constructor_args: ctor(3, CLAIM),
|
|
84
|
+
args: [x(BUYER_PK), x(PROVIDER_PK), PLACEHOLDER],
|
|
85
|
+
expect: 'fail',
|
|
86
|
+
tx: expireTx(3, CLAIM, [{ value: CLAIM, p2pk_pubkey: x('cc'.repeat(32)) }, toBuyer(FUNDED - CLAIM - FEE)]),
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
signer: STRANGER_SK,
|
|
91
|
+
case: {
|
|
92
|
+
name: 'A STRANGER CANNOT CLOSE: expire signed by neither party is refused',
|
|
93
|
+
function: 'expire',
|
|
94
|
+
constructor_args: ctor(3, CLAIM),
|
|
95
|
+
args: [x(BUYER_PK), x(PROVIDER_PK), PLACEHOLDER],
|
|
96
|
+
expect: 'fail',
|
|
97
|
+
tx: expireTx(3, CLAIM, [toProvider(CLAIM), toBuyer(FUNDED - CLAIM - FEE)]),
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
signer: BUYER_SK,
|
|
102
|
+
case: {
|
|
103
|
+
name: 'FINDING G: a claim too small to pay closes to the buyer instead of locking forever',
|
|
104
|
+
function: 'expire',
|
|
105
|
+
constructor_args: ctor(3, 100_000),
|
|
106
|
+
args: [x(BUYER_PK), x(PROVIDER_PK), PLACEHOLDER],
|
|
107
|
+
expect: 'pass',
|
|
108
|
+
tx: expireTx(3, 100_000, [toBuyer(FUNDED - FEE)]),
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
signer: PROVIDER_SK,
|
|
113
|
+
case: {
|
|
114
|
+
name: 'FINDING G: a dust claim may NOT be paid to the provider -- it cannot be created',
|
|
115
|
+
function: 'expire',
|
|
116
|
+
constructor_args: ctor(3, 100_000),
|
|
117
|
+
args: [x(BUYER_PK), x(PROVIDER_PK), PLACEHOLDER],
|
|
118
|
+
expect: 'fail',
|
|
119
|
+
tx: expireTx(3, 100_000, [toProvider(100_000), toBuyer(FUNDED - 100_000 - FEE)]),
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
signer: BUYER_SK,
|
|
124
|
+
case: {
|
|
125
|
+
// THE WINDOW THAT USED TO STRAND THE FUNDS. With the dust constant at 2,000,000 this claim
|
|
126
|
+
// took the two-output branch, which demanded an output of exactly 2,100,000 -- and KIP-9
|
|
127
|
+
// refuses to create one that small beside a large refund, so the session had NO legal close
|
|
128
|
+
// at all. tools/dust-map.ts found the window; 2,600,000 folds it to the buyer instead.
|
|
129
|
+
name: 'THE UNCLOSABLE WINDOW: a claim just above the old dust line folds, it does not strand',
|
|
130
|
+
function: 'expire',
|
|
131
|
+
constructor_args: ctor(3, 2_100_000),
|
|
132
|
+
args: [x(BUYER_PK), x(PROVIDER_PK), PLACEHOLDER],
|
|
133
|
+
expect: 'pass',
|
|
134
|
+
tx: expireTx(3, 2_100_000, [toBuyer(FUNDED - FEE)]),
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
signer: PROVIDER_SK,
|
|
139
|
+
case: {
|
|
140
|
+
// The other half: it must NOT be payable to the provider, because it still cannot be
|
|
141
|
+
// created. A fold that merely moved the problem would be no fix.
|
|
142
|
+
name: 'THE UNCLOSABLE WINDOW: that same claim still may not be paid to the provider',
|
|
143
|
+
function: 'expire',
|
|
144
|
+
constructor_args: ctor(3, 2_100_000),
|
|
145
|
+
args: [x(BUYER_PK), x(PROVIDER_PK), PLACEHOLDER],
|
|
146
|
+
expect: 'fail',
|
|
147
|
+
tx: expireTx(3, 2_100_000, [toProvider(2_100_000), toBuyer(FUNDED - 2_100_000 - FEE)]),
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
signer: PROVIDER_SK,
|
|
152
|
+
case: {
|
|
153
|
+
name: 'FINDING H: a one-output close that burns a payable refund to fee is refused',
|
|
154
|
+
function: 'expire',
|
|
155
|
+
constructor_args: ctor(3, CLAIM),
|
|
156
|
+
args: [x(BUYER_PK), x(PROVIDER_PK), PLACEHOLDER],
|
|
157
|
+
expect: 'fail',
|
|
158
|
+
tx: expireTx(3, CLAIM, [toProvider(CLAIM)]),
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
signer: PROVIDER_SK,
|
|
163
|
+
case: {
|
|
164
|
+
name: 'a refund too small to pay folds into the provider, rather than locking the balance',
|
|
165
|
+
function: 'expire',
|
|
166
|
+
constructor_args: ctor(3, FUNDED - 1_000_000),
|
|
167
|
+
args: [x(BUYER_PK), x(PROVIDER_PK), PLACEHOLDER],
|
|
168
|
+
expect: 'pass',
|
|
169
|
+
tx: expireTx(3, FUNDED - 1_000_000, [toProvider(FUNDED - 1_000_000)]),
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
signer: PROVIDER_SK,
|
|
174
|
+
case: {
|
|
175
|
+
name: 'FINDING J: two covenant inputs paying out once is refused -- input-group closure',
|
|
176
|
+
function: 'expire',
|
|
177
|
+
constructor_args: ctor(3, CLAIM),
|
|
178
|
+
args: [x(BUYER_PK), x(PROVIDER_PK), PLACEHOLDER],
|
|
179
|
+
expect: 'fail',
|
|
180
|
+
tx: {
|
|
181
|
+
active_input_index: 0,
|
|
182
|
+
inputs: [
|
|
183
|
+
{ utxo_value: FUNDED, sequence: WINDOW, constructor_args: ctor(3, CLAIM) },
|
|
184
|
+
{ utxo_value: FUNDED, sequence: WINDOW, constructor_args: ctor(3, CLAIM) },
|
|
185
|
+
],
|
|
186
|
+
outputs: [toProvider(CLAIM), toBuyer(FUNDED - CLAIM - FEE)],
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
signer: BUYER_SK,
|
|
192
|
+
case: {
|
|
193
|
+
name: 'P10/THE EARLY CLOSE: expiring before the response window has passed is refused',
|
|
194
|
+
function: 'expire',
|
|
195
|
+
constructor_args: ctor(3, CLAIM),
|
|
196
|
+
args: [x(BUYER_PK), x(PROVIDER_PK), PLACEHOLDER],
|
|
197
|
+
expect: 'fail',
|
|
198
|
+
tx: expireTx(3, CLAIM, [toProvider(CLAIM), toBuyer(FUNDED - CLAIM - FEE)], WINDOW - 1),
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
];
|
|
202
|
+
/** Ask the VM for each case's sighash, sign it, and return the cases with real signatures. */
|
|
203
|
+
export function buildExpireCases(contractPath) {
|
|
204
|
+
return PLAN.map(({ case: testCase, signer }) => {
|
|
205
|
+
const sighash = sighashFor(contractPath, testCase);
|
|
206
|
+
const args = [...testCase.args];
|
|
207
|
+
args[2] = x(signSighash(sighash, signer));
|
|
208
|
+
return { ...testCase, args };
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=expire-cases.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expire-cases.js","sourceRoot":"","sources":["../../tools/expire-cases.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fee-check.d.ts","sourceRoot":"","sources":["../../tools/fee-check.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `npm run fee-check` -- does the covenant's compiled-in fee allowance hold on MAINNET?
|
|
3
|
+
*
|
|
4
|
+
* WHY THIS CANNOT WAIT UNTIL AFTER A DEPLOYMENT. `expire` reserves 400,000 sompi for the
|
|
5
|
+
* transaction that closes a session, and that number is COMPILED INTO THE SCRIPT. If mainnet
|
|
6
|
+
* prices the close above it, the covenant demands an output it cannot afford to pay for, no valid
|
|
7
|
+
* close exists, and the balance is stranded -- with no way to patch the script that stranded it.
|
|
8
|
+
* Finding E cost a live spend to learn the allowance was below the minimum; this asks the same
|
|
9
|
+
* question of a different network, in advance.
|
|
10
|
+
*
|
|
11
|
+
* THE SDK'S FEE CALCULATOR IS NOT THE ORACLE HERE, and finding that out was the point of writing
|
|
12
|
+
* this. `calculateTransactionFee` returns `undefined` above `maximumStandardTransactionMass`,
|
|
13
|
+
* which is 100,000 on both networks -- and a two-output close of this covenant has a STORAGE mass
|
|
14
|
+
* of 251,929, because KIP-9 prices an output by its reciprocal and a 4,000,000-sompi payout is
|
|
15
|
+
* expensive by that measure. So the SDK refuses to price a transaction THIS PROJECT HAS REPEATEDLY
|
|
16
|
+
* LANDED ON CHAIN: 100,000 is a standard-transaction policy, while the consensus limit KIP-9
|
|
17
|
+
* enforces is 500,000, which tools/dust-map.ts models against a real rejection.
|
|
18
|
+
*
|
|
19
|
+
* So this reports three things separately rather than one number: what the two networks' rules
|
|
20
|
+
* are, what the compute fee is where the SDK will price it, and where each shape sits against the
|
|
21
|
+
* consensus storage limit. A single "fits" would have hidden all of it.
|
|
22
|
+
*/
|
|
23
|
+
import { mkdtempSync } from 'node:fs';
|
|
24
|
+
import { tmpdir } from 'node:os';
|
|
25
|
+
import { join } from 'node:path';
|
|
26
|
+
import { loadSdk } from './kaspa.js';
|
|
27
|
+
import { CLOSE_FEE_SOMPI } from '../src/reservation.js';
|
|
28
|
+
import { compileWithState } from './covenant.js';
|
|
29
|
+
import { buildExpire } from './live-steps.js';
|
|
30
|
+
import { publicKeyHex } from '../src/encoding.js';
|
|
31
|
+
const FUNDED = 50000000n;
|
|
32
|
+
/**
|
|
33
|
+
* Build the REAL close transaction, with the real redeem script and a real signature.
|
|
34
|
+
*
|
|
35
|
+
* An earlier version of this file modelled the transaction by hand and reported a mass of 251,929
|
|
36
|
+
* with a fee of zero -- the fee was `undefined`, meaning the SDK could not price it, and a `?? 0n`
|
|
37
|
+
* turned that into a pass. Measuring the real thing removes both the model and the excuse.
|
|
38
|
+
*/
|
|
39
|
+
const dir = mkdtempSync(join(tmpdir(), 'metered-fee-'));
|
|
40
|
+
const BUYER_SK = '11'.repeat(32);
|
|
41
|
+
const PROVIDER_SK = '22'.repeat(32);
|
|
42
|
+
function closeTx(sdk, network, outputs) {
|
|
43
|
+
const networkId = new sdk.NetworkId(network);
|
|
44
|
+
const buyer = new sdk.PrivateKey(BUYER_SK).toKeypair().toAddress(networkId).toString();
|
|
45
|
+
const provider = new sdk.PrivateKey(PROVIDER_SK).toKeypair().toAddress(networkId).toString();
|
|
46
|
+
const built = compileWithState(dir, {
|
|
47
|
+
parties: 'cd'.repeat(32), sessionId: 'a1'.repeat(16), window: 2, seq: 3, sompi: 4_000_000,
|
|
48
|
+
});
|
|
49
|
+
const utxo = {
|
|
50
|
+
address: buyer,
|
|
51
|
+
outpoint: { transactionId: 'ab'.repeat(32), index: 0 },
|
|
52
|
+
amount: FUNDED,
|
|
53
|
+
scriptPublicKey: sdk.payToScriptHashScript(built.hex),
|
|
54
|
+
blockDaaScore: 1n,
|
|
55
|
+
isCoinbase: false,
|
|
56
|
+
};
|
|
57
|
+
const addrs = [provider, buyer];
|
|
58
|
+
return buildExpire(sdk, {
|
|
59
|
+
buyerPk: publicKeyHex(BUYER_SK), providerPk: publicKeyHex(PROVIDER_SK), signerSk: BUYER_SK,
|
|
60
|
+
redeem: built.hex, tag: built.entries.expire?.dispatch_tag ?? '',
|
|
61
|
+
}, utxo, outputs.map((amount, i) => ({ address: addrs[i] ?? buyer, amount })), 2);
|
|
62
|
+
}
|
|
63
|
+
const SHAPES = [
|
|
64
|
+
{ name: 'two outputs (provider + buyer)', outputs: [4000000n, FUNDED - 4000000n - BigInt(CLOSE_FEE_SOMPI)] },
|
|
65
|
+
{ name: 'one output, folded', outputs: [FUNDED - BigInt(CLOSE_FEE_SOMPI)] },
|
|
66
|
+
];
|
|
67
|
+
/** KIP-9's consensus limit on storage mass, validated against a real rejection in dust-map.ts. */
|
|
68
|
+
const STORAGE_LIMIT = 500000n;
|
|
69
|
+
/** Price every close shape on every network, and return the fees the SDK is willing to quote. */
|
|
70
|
+
function reportShapes(sdk, networks) {
|
|
71
|
+
console.log('\n 2. WHAT EACH CLOSE SHAPE COSTS');
|
|
72
|
+
console.log(` ${'shape'.padEnd(32)}${'network'.padEnd(13)}${'mass'.padStart(9)}${'fee'.padStart(11)}`);
|
|
73
|
+
const fees = [];
|
|
74
|
+
for (const shape of SHAPES) {
|
|
75
|
+
for (const network of networks) {
|
|
76
|
+
const tx = closeTx(sdk, network, shape.outputs);
|
|
77
|
+
const mass = sdk.calculateTransactionMass(network, tx);
|
|
78
|
+
const priced = sdk.calculateTransactionFee(network, tx);
|
|
79
|
+
if (priced !== undefined)
|
|
80
|
+
fees.push(priced);
|
|
81
|
+
const shown = priced === undefined ? 'unpriced' : String(priced);
|
|
82
|
+
console.log(` ${shape.name.padEnd(32)}${network.padEnd(13)}${String(mass).padStart(9)}${shown.padStart(11)}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
console.log(' "unpriced" = above the 100,000 STANDARD-transaction policy, not above consensus.');
|
|
86
|
+
return fees;
|
|
87
|
+
}
|
|
88
|
+
async function main() {
|
|
89
|
+
const sdk = await loadSdk();
|
|
90
|
+
const networks = ['mainnet', 'testnet-10'];
|
|
91
|
+
console.log(`
|
|
92
|
+
COVENANT FEE ALLOWANCE: ${CLOSE_FEE_SOMPI.toLocaleString()} sompi, compiled into the script
|
|
93
|
+
`);
|
|
94
|
+
console.log(' 1. DO THE TWO NETWORKS PRICE ALIKE?');
|
|
95
|
+
const limits = networks.map((n) => String(sdk.maximumStandardTransactionMass(n)));
|
|
96
|
+
for (const [i, n] of networks.entries()) {
|
|
97
|
+
console.log(` ${n.padEnd(12)} maximumStandardTransactionMass ${limits[i]}`);
|
|
98
|
+
}
|
|
99
|
+
const alike = new Set(limits).size === 1;
|
|
100
|
+
console.log(` ${alike ? 'IDENTICAL' : 'THEY DIFFER -- do not assume testnet measurements carry over'}`);
|
|
101
|
+
const fees = reportShapes(sdk, networks);
|
|
102
|
+
console.log('\n 3. WHERE EACH SHAPE SITS AGAINST THE KIP-9 CONSENSUS LIMIT');
|
|
103
|
+
for (const shape of SHAPES) {
|
|
104
|
+
// Numbers, not bigints: the signature says Array<number>, and bigints panic inside the WASM.
|
|
105
|
+
const storage = sdk.calculateStorageMass('mainnet', [Number(FUNDED)], shape.outputs.map(Number));
|
|
106
|
+
const ok = storage !== undefined && storage <= STORAGE_LIMIT;
|
|
107
|
+
console.log(` ${shape.name.padEnd(32)}storage mass ${String(storage).padStart(7)} / ${STORAGE_LIMIT} ${ok ? 'legal' : 'REFUSED'}`);
|
|
108
|
+
}
|
|
109
|
+
const worst = fees.reduce((a, b) => (b > a ? b : a), 0n);
|
|
110
|
+
const headroom = BigInt(CLOSE_FEE_SOMPI) - worst;
|
|
111
|
+
console.log(`
|
|
112
|
+
WORST PRICED FEE ${worst.toLocaleString()} sompi, allowance ${CLOSE_FEE_SOMPI.toLocaleString()}, headroom ${headroom.toLocaleString()}`);
|
|
113
|
+
if (headroom < 0n) {
|
|
114
|
+
console.log('\n THE ALLOWANCE IS TOO SMALL. Do not deploy: closes would be unaffordable.\n');
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
117
|
+
if (!alike)
|
|
118
|
+
process.exit(1);
|
|
119
|
+
console.log(' Both networks price identically, and the allowance covers the worst of them.\n');
|
|
120
|
+
}
|
|
121
|
+
main().catch((err) => {
|
|
122
|
+
console.error(`
|
|
123
|
+
${err instanceof Error ? err.message : String(err)}
|
|
124
|
+
`);
|
|
125
|
+
process.exit(1);
|
|
126
|
+
});
|
|
127
|
+
//# sourceMappingURL=fee-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fee-check.js","sourceRoot":"","sources":["../../tools/fee-check.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export declare const BUYER_SK: string;
|
|
2
|
+
export declare const PROVIDER_SK: string;
|
|
3
|
+
export declare const STRANGER_SK: string;
|
|
4
|
+
export declare const BUYER_PK: string;
|
|
5
|
+
export declare const PROVIDER_PK: string;
|
|
6
|
+
export declare const STRANGER_PK: string;
|
|
7
|
+
export declare const SESSION_ID: string;
|
|
8
|
+
export declare const WINDOW = 10;
|
|
9
|
+
export declare const FUNDED = 10000000;
|
|
10
|
+
/**
|
|
11
|
+
* MUST equal the covenant's fee allowance. It is not a test convenience: THE DRAIN case works by
|
|
12
|
+
* keeping one sompi more than the contract permits, so if this drifts below the contract's figure
|
|
13
|
+
* the case stops testing anything and passes for the wrong reason. It did exactly that when the
|
|
14
|
+
* allowance was raised from 100,000, and the suite caught it.
|
|
15
|
+
*/
|
|
16
|
+
export declare const FEE = 400000;
|
|
17
|
+
/** The covenant's `parties`: blake3 over the two x-only keys, concatenated raw. */
|
|
18
|
+
export declare const PARTIES: string;
|
|
19
|
+
export declare const x: (hex: string) => string;
|
|
20
|
+
/** Constructor arguments in declaration order, carrying whatever claim is currently pending. */
|
|
21
|
+
export declare const ctor: (pendingSeq: number, pendingSompi: number) => (string | number)[];
|
|
22
|
+
export interface Case {
|
|
23
|
+
name: string;
|
|
24
|
+
function: string;
|
|
25
|
+
constructor_args: unknown[];
|
|
26
|
+
args: unknown[];
|
|
27
|
+
expect: 'pass' | 'fail';
|
|
28
|
+
tx: unknown;
|
|
29
|
+
}
|
|
30
|
+
export interface State {
|
|
31
|
+
v: number;
|
|
32
|
+
sessionId: string;
|
|
33
|
+
seq: number;
|
|
34
|
+
cumulativeUnits: number;
|
|
35
|
+
cumulativeSompi: number;
|
|
36
|
+
prevState: string | null;
|
|
37
|
+
}
|
|
38
|
+
export declare const state: (seq: number, units: number, sompi: number, prev?: string | null) => State;
|
|
39
|
+
//# sourceMappingURL=fixtures.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../tools/fixtures.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,QAAQ,QAAkB,CAAC;AACxC,eAAO,MAAM,WAAW,QAAkB,CAAC;AAC3C,eAAO,MAAM,WAAW,QAAkB,CAAC;AAE3C,eAAO,MAAM,QAAQ,QAAyB,CAAC;AAC/C,eAAO,MAAM,WAAW,QAA4B,CAAC;AACrD,eAAO,MAAM,WAAW,QAA4B,CAAC;AAErD,eAAO,MAAM,UAAU,QAAkB,CAAC;AAC1C,eAAO,MAAM,MAAM,KAAK,CAAC;AACzB,eAAO,MAAM,MAAM,WAAa,CAAC;AACjC;;;;;GAKG;AACH,eAAO,MAAM,GAAG,SAAU,CAAC;AAE3B,mFAAmF;AACnF,eAAO,MAAM,OAAO,QAEnB,CAAC;AAEF,eAAO,MAAM,CAAC,GAAI,KAAK,MAAM,WAAe,CAAC;AAE7C,gGAAgG;AAChG,eAAO,MAAM,IAAI,GAAI,YAAY,MAAM,EAAE,cAAc,MAAM,wBACE,CAAC;AAEhE,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,OAAO,EAAE,CAAC;IAC5B,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,EAAE,EAAE,OAAO,CAAC;CACb;AAED,MAAM,WAAW,KAAK;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,eAAO,MAAM,KAAK,GAAI,KAAK,MAAM,EAAE,OAAO,MAAM,EAAE,OAAO,MAAM,EAAE,OAAM,MAAM,GAAG,IAAW,KAAG,KACW,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared fixtures for the covenant's simulator suite. One place, so the settle cases and the
|
|
3
|
+
* expire cases cannot drift into disagreeing about who the parties are -- which would look like a
|
|
4
|
+
* contract bug and be a test bug.
|
|
5
|
+
*/
|
|
6
|
+
import { blake3 } from '@noble/hashes/blake3';
|
|
7
|
+
import { bytesToHex, hexToBytes } from '@noble/hashes/utils';
|
|
8
|
+
import { publicKeyHex } from '../src/encoding.js';
|
|
9
|
+
export const BUYER_SK = '11'.repeat(32);
|
|
10
|
+
export const PROVIDER_SK = '22'.repeat(32);
|
|
11
|
+
export const STRANGER_SK = '33'.repeat(32);
|
|
12
|
+
export const BUYER_PK = publicKeyHex(BUYER_SK);
|
|
13
|
+
export const PROVIDER_PK = publicKeyHex(PROVIDER_SK);
|
|
14
|
+
export const STRANGER_PK = publicKeyHex(STRANGER_SK);
|
|
15
|
+
export const SESSION_ID = 'a1'.repeat(16);
|
|
16
|
+
export const WINDOW = 10;
|
|
17
|
+
export const FUNDED = 10_000_000;
|
|
18
|
+
/**
|
|
19
|
+
* MUST equal the covenant's fee allowance. It is not a test convenience: THE DRAIN case works by
|
|
20
|
+
* keeping one sompi more than the contract permits, so if this drifts below the contract's figure
|
|
21
|
+
* the case stops testing anything and passes for the wrong reason. It did exactly that when the
|
|
22
|
+
* allowance was raised from 100,000, and the suite caught it.
|
|
23
|
+
*/
|
|
24
|
+
export const FEE = 400_000;
|
|
25
|
+
/** The covenant's `parties`: blake3 over the two x-only keys, concatenated raw. */
|
|
26
|
+
export const PARTIES = bytesToHex(blake3(new Uint8Array([...hexToBytes(BUYER_PK), ...hexToBytes(PROVIDER_PK)]), { dkLen: 32 }));
|
|
27
|
+
export const x = (hex) => `0x${hex}`;
|
|
28
|
+
/** Constructor arguments in declaration order, carrying whatever claim is currently pending. */
|
|
29
|
+
export const ctor = (pendingSeq, pendingSompi) => [x(PARTIES), x(SESSION_ID), WINDOW, pendingSeq, pendingSompi];
|
|
30
|
+
export const state = (seq, units, sompi, prev = null) => ({ v: 1, sessionId: SESSION_ID, seq, cumulativeUnits: units, cumulativeSompi: sompi, prevState: prev });
|
|
31
|
+
//# sourceMappingURL=fixtures.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixtures.js","sourceRoot":"","sources":["../../tools/fixtures.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AACxC,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAC3C,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAE3C,MAAM,CAAC,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;AAC/C,MAAM,CAAC,MAAM,WAAW,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;AACrD,MAAM,CAAC,MAAM,WAAW,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;AAErD,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAC1C,MAAM,CAAC,MAAM,MAAM,GAAG,EAAE,CAAC;AACzB,MAAM,CAAC,MAAM,MAAM,GAAG,UAAU,CAAC;AACjC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,OAAO,CAAC;AAE3B,mFAAmF;AACnF,MAAM,CAAC,MAAM,OAAO,GAAG,UAAU,CAC/B,MAAM,CAAC,IAAI,UAAU,CAAC,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAC7F,CAAC;AAEF,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,KAAK,GAAG,EAAE,CAAC;AAE7C,gGAAgG;AAChG,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,UAAkB,EAAE,YAAoB,EAAE,EAAE,CAC/D,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;AAoBhE,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,GAAW,EAAE,KAAa,EAAE,KAAa,EAAE,OAAsB,IAAI,EAAS,EAAE,CACpG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gen-contract-tests.d.ts","sourceRoot":"","sources":["../../tools/gen-contract-tests.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `npm run contracts:gen` -- generate the covenant's simulator suite, with REAL signatures.
|
|
3
|
+
*
|
|
4
|
+
* Why this exists. Both entry points check a signature before doing anything else, and the
|
|
5
|
+
* SilverScript simulator verifies signatures for real -- it hands `sig`/`datasig` to the VM as
|
|
6
|
+
* opaque blobs. So a hand-written test file cannot execute a single line of this contract.
|
|
7
|
+
* kaspa-depin never tested a signature path for exactly this reason; its only suite covers
|
|
8
|
+
* `topUp`, which needs no key.
|
|
9
|
+
*
|
|
10
|
+
* The two entries need different treatment. `settle` uses `checkMsgSig` (OpCheckSigFromStack),
|
|
11
|
+
* which verifies a signature over SUPPLIED DATA -- the signed message is just the 32-byte
|
|
12
|
+
* settlement digest, so it can be signed here and now. `expire` uses `checkSig`, which covers the
|
|
13
|
+
* spending transaction, and that needs the two-pass harness in tools/sighash.ts.
|
|
14
|
+
*
|
|
15
|
+
* The settle signatures come from src/encoding.ts -- the same code the protocol signs with. If the
|
|
16
|
+
* covenant and the encoder ever disagree about the 72-byte preimage of SPEC.md 3.4.1, these tests
|
|
17
|
+
* fail. That is the point: this is a conformance test between two independent implementations of
|
|
18
|
+
* the same spec, not a mock of either.
|
|
19
|
+
*/
|
|
20
|
+
import { writeFileSync } from 'node:fs';
|
|
21
|
+
import { blake3 } from '@noble/hashes/blake3';
|
|
22
|
+
import { bytesToHex } from '@noble/hashes/utils';
|
|
23
|
+
import { signState, settlementPreimage } from '../src/encoding.js';
|
|
24
|
+
import { buildExpireCases } from './expire-cases.js';
|
|
25
|
+
import { settleArgs } from './sigscript.js';
|
|
26
|
+
import { profileFromArgv, COVENANT_ID } from './covenant-profile.js';
|
|
27
|
+
import { BUYER_SK, PROVIDER_SK, STRANGER_SK, BUYER_PK, PROVIDER_PK, STRANGER_PK, SESSION_ID, WINDOW, FUNDED, FEE, PARTIES, ctor, x, state, } from './fixtures.js';
|
|
28
|
+
const PROFILE = profileFromArgv();
|
|
29
|
+
/** This suite's session, in whichever field names the profile's covenant uses. */
|
|
30
|
+
const sessionState = (seq, sompi, sessionId = SESSION_ID) => PROFILE.outState({ parties: PARTIES, sessionId, window: WINDOW, seq, sompi });
|
|
31
|
+
/**
|
|
32
|
+
* KIP-20 bindings for a settle. Argent's `emits next` lowers to OpAuthOutputCount == 1, so its
|
|
33
|
+
* continuation output must be AUTHORISED by the spending input rather than merely sitting at
|
|
34
|
+
* index 0. The hand-written covenant asks for no binding and gets none.
|
|
35
|
+
*/
|
|
36
|
+
const bindInput = () => (PROFILE.binds ? { covenant_id: COVENANT_ID } : {});
|
|
37
|
+
const bindOutput = () => (PROFILE.binds ? { covenant_id: COVENANT_ID, authorizing_input: 0 } : {});
|
|
38
|
+
/** The arguments `settle` takes, signed by whichever keys the case calls for. */
|
|
39
|
+
function signedSettleArgs(s, buyerSk = BUYER_SK, providerSk = PROVIDER_SK, buyerPk = BUYER_PK, providerPk = PROVIDER_PK) {
|
|
40
|
+
return settleArgs(s, buyerPk, providerPk, signState(s, buyerSk), signState(s, providerSk));
|
|
41
|
+
}
|
|
42
|
+
/** A settle spends the covenant and hands it straight back, carrying the new claim. */
|
|
43
|
+
function settleTx(pendingSeq, pendingSompi, s, outValue = FUNDED - FEE, outState) {
|
|
44
|
+
return {
|
|
45
|
+
active_input_index: 0,
|
|
46
|
+
inputs: [{ utxo_value: FUNDED, constructor_args: ctor(pendingSeq, pendingSompi), ...bindInput() }],
|
|
47
|
+
outputs: [{
|
|
48
|
+
value: outValue,
|
|
49
|
+
constructor_args: ctor(pendingSeq, pendingSompi),
|
|
50
|
+
state: outState ?? sessionState(s.seq, s.cumulativeSompi),
|
|
51
|
+
...bindOutput(),
|
|
52
|
+
}],
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const digestOf = (s) => bytesToHex(blake3(settlementPreimage(s), { dkLen: 32 }));
|
|
56
|
+
const FIRST = state(0, 550, 1_000_000);
|
|
57
|
+
const SECOND = state(1, 1100, 2_000_000, digestOf(FIRST));
|
|
58
|
+
const OTHER_ID = 'c3'.repeat(16);
|
|
59
|
+
const OTHER_SESSION = ctor(-1, 0).map((v, i) => (i === 1 ? x(OTHER_ID) : v));
|
|
60
|
+
const settleCases = [
|
|
61
|
+
{
|
|
62
|
+
name: 'the first claim: a doubly-signed State at seq 0 posts, and pays nobody',
|
|
63
|
+
function: 'settle',
|
|
64
|
+
constructor_args: ctor(-1, 0),
|
|
65
|
+
args: signedSettleArgs(FIRST),
|
|
66
|
+
expect: 'pass',
|
|
67
|
+
tx: settleTx(-1, 0, FIRST),
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: 'SUPERSEDE: a strictly higher seq replaces the pending claim',
|
|
71
|
+
function: 'settle',
|
|
72
|
+
constructor_args: ctor(0, 1_000_000),
|
|
73
|
+
args: signedSettleArgs(SECOND),
|
|
74
|
+
expect: 'pass',
|
|
75
|
+
tx: settleTx(0, 1_000_000, SECOND),
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: 'P6/B5 THE STALE CLOSE: re-posting the SAME seq over a pending claim is refused',
|
|
79
|
+
function: 'settle',
|
|
80
|
+
constructor_args: ctor(0, 1_000_000),
|
|
81
|
+
args: signedSettleArgs(FIRST),
|
|
82
|
+
expect: 'fail',
|
|
83
|
+
tx: settleTx(0, 1_000_000, FIRST),
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: 'a LOWER seq than the pending claim is refused -- supersede is strict, not >=',
|
|
87
|
+
function: 'settle',
|
|
88
|
+
constructor_args: ctor(5, 9_000_000),
|
|
89
|
+
args: signedSettleArgs(FIRST),
|
|
90
|
+
expect: 'fail',
|
|
91
|
+
tx: settleTx(5, 9_000_000, FIRST),
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
name: 'THE FORGERY: a State signed by a stranger instead of the buyer is refused',
|
|
95
|
+
function: 'settle',
|
|
96
|
+
constructor_args: ctor(-1, 0),
|
|
97
|
+
args: signedSettleArgs(FIRST, STRANGER_SK, PROVIDER_SK, STRANGER_PK, PROVIDER_PK),
|
|
98
|
+
expect: 'fail',
|
|
99
|
+
tx: settleTx(-1, 0, FIRST),
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
name: 'ONE SIGNATURE IS NOT A STATE: the provider signing both halves is refused',
|
|
103
|
+
function: 'settle',
|
|
104
|
+
constructor_args: ctor(-1, 0),
|
|
105
|
+
args: signedSettleArgs(FIRST, PROVIDER_SK, PROVIDER_SK, PROVIDER_PK, PROVIDER_PK),
|
|
106
|
+
expect: 'fail',
|
|
107
|
+
tx: settleTx(-1, 0, FIRST),
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
name: 'X1 CROSS-SESSION REPLAY: a State signed for another session is refused',
|
|
111
|
+
function: 'settle',
|
|
112
|
+
constructor_args: OTHER_SESSION,
|
|
113
|
+
args: signedSettleArgs(FIRST),
|
|
114
|
+
expect: 'fail',
|
|
115
|
+
tx: {
|
|
116
|
+
active_input_index: 0,
|
|
117
|
+
inputs: [{ utxo_value: FUNDED, constructor_args: OTHER_SESSION, ...bindInput() }],
|
|
118
|
+
outputs: [{
|
|
119
|
+
value: FUNDED - FEE,
|
|
120
|
+
constructor_args: OTHER_SESSION,
|
|
121
|
+
state: sessionState(FIRST.seq, FIRST.cumulativeSompi, OTHER_ID),
|
|
122
|
+
...bindOutput(),
|
|
123
|
+
}],
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: 'THE DRAIN: a settle keeping more than the fee instead of returning the funds is refused',
|
|
128
|
+
function: 'settle',
|
|
129
|
+
constructor_args: ctor(-1, 0),
|
|
130
|
+
args: signedSettleArgs(FIRST),
|
|
131
|
+
expect: 'fail',
|
|
132
|
+
tx: settleTx(-1, 0, FIRST, FUNDED - FEE - 1),
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
name: 'THE LIE: a settle whose carried state does not match the State it verified is refused',
|
|
136
|
+
function: 'settle',
|
|
137
|
+
constructor_args: ctor(-1, 0),
|
|
138
|
+
args: signedSettleArgs(FIRST),
|
|
139
|
+
expect: 'fail',
|
|
140
|
+
tx: settleTx(-1, 0, FIRST, FUNDED - FEE, sessionState(FIRST.seq, 9_000_000)),
|
|
141
|
+
},
|
|
142
|
+
];
|
|
143
|
+
/**
|
|
144
|
+
* THE CASE THAT JUSTIFIES THE 16 BYTES, and it can only be written against Argent.
|
|
145
|
+
*
|
|
146
|
+
* In the hand-written covenant `sessionId` is a constructor constant, so a continuation cannot be
|
|
147
|
+
* ASKED to rewrite it -- the field is not in the state block, and the case does not exist. In
|
|
148
|
+
* Argent it is state, `become` rewrites the whole of it, and the compiler emits a continuation
|
|
149
|
+
* that checks every field. That is what the extra 16 bytes bought, and without
|
|
150
|
+
* this case that claim is an assertion about a compiler rather than a measurement of one.
|
|
151
|
+
*
|
|
152
|
+
* Verified to refuse at `validateOutputState`, with the covenant's own computed `next_state`
|
|
153
|
+
* carrying the original session_id against an output claiming another.
|
|
154
|
+
*/
|
|
155
|
+
const identityCases = PROFILE.identityInState
|
|
156
|
+
? [{
|
|
157
|
+
name: 'IDENTITY DRIFT: a continuation that rewrites the session_id it carries is refused',
|
|
158
|
+
function: 'settle',
|
|
159
|
+
constructor_args: ctor(-1, 0),
|
|
160
|
+
args: signedSettleArgs(FIRST),
|
|
161
|
+
expect: 'fail',
|
|
162
|
+
tx: settleTx(-1, 0, FIRST, FUNDED - FEE, sessionState(FIRST.seq, FIRST.cumulativeSompi, 'c3'.repeat(16))),
|
|
163
|
+
}]
|
|
164
|
+
: [];
|
|
165
|
+
const cases = [...settleCases, ...identityCases, ...buildExpireCases(PROFILE.contract)];
|
|
166
|
+
writeFileSync(PROFILE.suite, `${JSON.stringify({ tests: cases }, null, 2)}\n`);
|
|
167
|
+
console.log(`wrote ${PROFILE.suite} -- ${cases.length} cases [${PROFILE.key}: ${PROFILE.contract}]`);
|
|
168
|
+
console.log(` session ${SESSION_ID} window ${WINDOW} funded ${FUNDED}`);
|
|
169
|
+
console.log(` parties ${PARTIES}`);
|
|
170
|
+
//# sourceMappingURL=gen-contract-tests.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gen-contract-tests.js","sourceRoot":"","sources":["../../tools/gen-contract-tests.ts"],"names":[],"mappings":"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"}
|