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,135 @@
|
|
|
1
|
+
// The metered session covenant, in Argent.
|
|
2
|
+
//
|
|
3
|
+
// A port of contracts/metered_session.sil, which is hand-written SilverScript at 520 of 520 bytes
|
|
4
|
+
// with zero spare. Argent compiles to SilverScript, so this does not replace that toolchain --
|
|
5
|
+
// it sits above it. The reason to move is not novelty:
|
|
6
|
+
//
|
|
7
|
+
// TWO OF THE FIVE FUND-LOSING BUGS FOUND IN THE HAND-WRITTEN VERSION CANNOT BE WRITTEN HERE.
|
|
8
|
+
//
|
|
9
|
+
// Finding H a one-output close constrained only outputs[0] and left the rest to fee, so a
|
|
10
|
+
// provider could burn the buyer's refund. `emits` declares the COMPLETE output
|
|
11
|
+
// shape, and Argent requires every declared output's value to be disposed of.
|
|
12
|
+
// Finding J two covenant inputs could satisfy one payout, destroying the other's balance.
|
|
13
|
+
// Input-group accounting is what the leader/delegate rules exist for, and
|
|
14
|
+
// `emits {}` lowers to a consensus-level `OpAuthOutputCount(...) == 0`.
|
|
15
|
+
//
|
|
16
|
+
// WHAT DOES NOT CHANGE. Argent proves the actor, template and successor-state relationships.
|
|
17
|
+
// Application rules stay explicit `require(...)` conditions, so every measured constant below --
|
|
18
|
+
// the 400,000 fee allowance, the 2,000,000 dust floor, the 2,400,000 fold threshold -- is the
|
|
19
|
+
// same number for the same reason, each measured rather than chosen.
|
|
20
|
+
|
|
21
|
+
state SessionState {
|
|
22
|
+
// Immutable for the life of the session; carried forward unchanged by every `become`.
|
|
23
|
+
// In the SilverScript version these were constructor constants outside the state span.
|
|
24
|
+
// Here they are state, which means the compiler CHECKS that a continuation preserves them
|
|
25
|
+
// rather than trusting the author to re-emit them correctly.
|
|
26
|
+
byte[32] parties;
|
|
27
|
+
byte[16] session_id;
|
|
28
|
+
int window;
|
|
29
|
+
|
|
30
|
+
// The pending claim. SPEC.md 7.4: integers only.
|
|
31
|
+
int pending_seq;
|
|
32
|
+
int pending_sompi;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
actor MeteredSession owns SessionState {
|
|
36
|
+
// POST A CLAIM (SPEC.md 7.2 `settle`). Pays nobody: it hands the funds back to this same
|
|
37
|
+
// actor carrying the agreed State, and restarts the response window. Supersede is the seq
|
|
38
|
+
// guard, not a separate entry.
|
|
39
|
+
entry settle(
|
|
40
|
+
pubkey buyer,
|
|
41
|
+
pubkey provider,
|
|
42
|
+
datasig buyer_sig,
|
|
43
|
+
datasig provider_sig,
|
|
44
|
+
int seq,
|
|
45
|
+
int cumulative_units,
|
|
46
|
+
int cumulative_sompi,
|
|
47
|
+
byte[32] prev_state
|
|
48
|
+
) emits next: MeteredSession {
|
|
49
|
+
require(blake3(byte[](buyer) + byte[](provider)) == parties);
|
|
50
|
+
|
|
51
|
+
// Strictly higher, so a stale State cannot replace a fresher one. pending_seq starts at
|
|
52
|
+
// -1, so this also implies seq >= 0 on every reachable path.
|
|
53
|
+
require(seq > pending_seq);
|
|
54
|
+
|
|
55
|
+
// cumulative_sompi is load-bearing: it becomes pending_sompi, whose value decides the
|
|
56
|
+
// close shape, and it is the amount actually paid out. The other two need no lower bound
|
|
57
|
+
// -- each omission below is argued rather than assumed.
|
|
58
|
+
require(cumulative_sompi >= 0);
|
|
59
|
+
|
|
60
|
+
// SPEC.md 3.4.1: sessionId(16) + seq(8) + cumUnits(8) + cumSompi(8) + prevState(32) = 72.
|
|
61
|
+
byte[32] digest = blake3(
|
|
62
|
+
byte[](session_id)
|
|
63
|
+
+ OpNum2Bin(seq, 8)
|
|
64
|
+
+ OpNum2Bin(cumulative_units, 8)
|
|
65
|
+
+ OpNum2Bin(cumulative_sompi, 8)
|
|
66
|
+
+ byte[](prev_state)
|
|
67
|
+
);
|
|
68
|
+
require(checkMsgSig(buyer_sig, digest, buyer));
|
|
69
|
+
require(checkMsgSig(provider_sig, digest, provider));
|
|
70
|
+
|
|
71
|
+
SessionState next_state = {
|
|
72
|
+
parties: parties,
|
|
73
|
+
session_id: session_id,
|
|
74
|
+
window: window,
|
|
75
|
+
pending_seq: seq,
|
|
76
|
+
pending_sompi: cumulative_sompi,
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// Written as an addition, never `self.value - fee`: subtraction can underflow, underflow
|
|
80
|
+
// is undefined, and SilverScript's undefined behaviour is fail-OPEN.
|
|
81
|
+
require(next.value + 400000 >= self.value);
|
|
82
|
+
become next <- MeteredSession(next_state);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// FINALISE (SPEC.md 7.2 `expire`). No successor: the session ends and the money is paid to
|
|
86
|
+
// the parties' own keys. `emits {}` is what says so, and lowers to a consensus check that
|
|
87
|
+
// this input authorises no continuation output at all.
|
|
88
|
+
entry expire(pubkey buyer, pubkey provider, sig party_sig) emits {} {
|
|
89
|
+
require(blake3(byte[](buyer) + byte[](provider)) == parties);
|
|
90
|
+
|
|
91
|
+
// SPEC.md 7.3: the window is RELATIVE, so ageDaa lowers to OpCheckSequenceVerify and
|
|
92
|
+
// reads the spending input's sequence field.
|
|
93
|
+
require(this.ageDaa >= window);
|
|
94
|
+
require(checkSig(party_sig, buyer) || checkSig(party_sig, provider));
|
|
95
|
+
|
|
96
|
+
// SPEC.md 7.2a, Finding J. This covenant accounts for exactly one input -- its own -- and
|
|
97
|
+
// the payouts below go to plain keys that carry no session identifier, so two sessions
|
|
98
|
+
// between the same parties would otherwise share one payout and destroy the other's
|
|
99
|
+
// balance. Measured before the rule existed: 10,400,000 sompi burned.
|
|
100
|
+
require(tx.inputs.length == 1);
|
|
101
|
+
|
|
102
|
+
byte[36] buyer_lock = new ScriptPubKeyP2PK(buyer);
|
|
103
|
+
|
|
104
|
+
// DUST (SPEC.md 7.4a). KIP-9 prices an output by its reciprocal, so MEASURED: see tools/dust-map.ts. Whichever side's share is dust, the other
|
|
105
|
+
// takes the lot: folding costs that party at most 0.02 KAS, and the alternative is
|
|
106
|
+
// locking the whole balance forever, which is what Finding G actually did.
|
|
107
|
+
// DUST (SPEC.md 7.4a), measured by tools/dust-map.ts rather than reasoned: the KIP-9
|
|
108
|
+
// floor is not a constant, and 2,000,000 left an unclosable window at every balance.
|
|
109
|
+
if (pending_sompi < 2600000) {
|
|
110
|
+
// The provider earned dust, which includes earning nothing. SPEC.md 7.2: expire
|
|
111
|
+
// "refunds the buyer entirely if none".
|
|
112
|
+
require(tx.outputs.length == 1);
|
|
113
|
+
require(tx.outputs[0].scriptPubKey == byte[](buyer_lock));
|
|
114
|
+
require(tx.outputs[0].value + 400000 >= self.value);
|
|
115
|
+
} else {
|
|
116
|
+
byte[36] provider_lock = new ScriptPubKeyP2PK(provider);
|
|
117
|
+
require(tx.outputs[0].value == pending_sompi);
|
|
118
|
+
require(tx.outputs[0].scriptPubKey == byte[](provider_lock));
|
|
119
|
+
if (tx.outputs.length == 1) {
|
|
120
|
+
// The buyer's refund is dust, so it goes to fee. The threshold is 2,400,000 and
|
|
121
|
+
// not 2,000,000 because the refund is self.value - pending_sompi - fee: the
|
|
122
|
+
// smaller bound would leave 1,600,000..2,000,000 with no legal shape at all.
|
|
123
|
+
require(pending_sompi + 3000000 >= self.value);
|
|
124
|
+
} else {
|
|
125
|
+
require(tx.outputs.length == 2);
|
|
126
|
+
require(tx.outputs[1].scriptPubKey == byte[](buyer_lock));
|
|
127
|
+
require(tx.outputs[1].value + pending_sompi + 400000 >= self.value);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
app Metered {
|
|
134
|
+
actor MeteredSession;
|
|
135
|
+
}
|