@obbyx/obyte 0.1.0 → 0.1.1
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/dist/unit/exact-unit.d.ts.map +1 -1
- package/dist/unit/exact-unit.js +135 -82
- package/dist/unit/exact-unit.js.map +1 -1
- package/package.json +1 -1
- package/src/unit/exact-unit.ts +145 -86
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exact-unit.d.ts","sourceRoot":"","sources":["../../src/unit/exact-unit.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,KAAK,OAAO,EAA8C,MAAM,mBAAmB,CAAC;AAC7F,OAAO,EAAE,KAAK,aAAa,EAAoC,MAAM,8BAA8B,CAAC;AAEpG;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;CAehB,CAAC;AAEX,+CAA+C;AAC/C,eAAO,MAAM,mBAAmB;;;CAA+C,CAAC;AAGhF,eAAO,MAAM,sBAAsB,QAAY,CAAC;AAEhD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,iEAAiE;IACjE,QAAQ,CAAC,oBAAoB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,QAAQ,EAAE,CAAC;IACrC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,iFAAiF;IACjF,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACxD,QAAQ,CAAC,WAAW,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7E,iFAAiF;IACjF,QAAQ,CAAC,oBAAoB,EAAE,OAAO,CAAC;CACxC;AA6BD,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,gBAAgB,EACxB,OAAO,GAAE;IAAE,gBAAgB,CAAC,EAAE,aAAa,CAAA;CAAO,GACjD,OAAO,CAAC,cAAc,CAAC,
|
|
1
|
+
{"version":3,"file":"exact-unit.d.ts","sourceRoot":"","sources":["../../src/unit/exact-unit.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,KAAK,OAAO,EAA8C,MAAM,mBAAmB,CAAC;AAC7F,OAAO,EAAE,KAAK,aAAa,EAAoC,MAAM,8BAA8B,CAAC;AAEpG;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;CAehB,CAAC;AAEX,+CAA+C;AAC/C,eAAO,MAAM,mBAAmB;;;CAA+C,CAAC;AAGhF,eAAO,MAAM,sBAAsB,QAAY,CAAC;AAEhD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,iEAAiE;IACjE,QAAQ,CAAC,oBAAoB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,QAAQ,EAAE,CAAC;IACrC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,iFAAiF;IACjF,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACxD,QAAQ,CAAC,WAAW,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7E,iFAAiF;IACjF,QAAQ,CAAC,oBAAoB,EAAE,OAAO,CAAC;CACxC;AA6BD,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,gBAAgB,EACxB,OAAO,GAAE;IAAE,gBAAgB,CAAC,EAAE,aAAa,CAAA;CAAO,GACjD,OAAO,CAAC,cAAc,CAAC,CAoCzB;AA+PD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAKtF;AAED,wBAAgB,cAAc,CAC5B,CAAC,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EACtC,CAAC,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACrC,MAAM,CAGR"}
|
package/dist/unit/exact-unit.js
CHANGED
|
@@ -65,9 +65,49 @@ const isHash = (v) => typeof v === 'string' && HASH_RE.test(v);
|
|
|
65
65
|
const isIndex = (v) => Number.isSafeInteger(v) && v >= 0;
|
|
66
66
|
const isPositiveAmount = (v) => Number.isSafeInteger(v) && v > 0;
|
|
67
67
|
export function validateExactUnit(unit, expect, options = {}) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
// The order of the checks is part of the contract: the first failing one
|
|
69
|
+
// decides the reason code.
|
|
70
|
+
const shaped = checkShape(unit, expect);
|
|
71
|
+
if (!shaped.ok)
|
|
72
|
+
return shaped;
|
|
73
|
+
const u = shaped.value;
|
|
74
|
+
const hashed = checkUnitHash(u);
|
|
75
|
+
if (!hashed.ok)
|
|
76
|
+
return hashed;
|
|
77
|
+
const { unitHash, messages, authors } = hashed.value;
|
|
78
|
+
const author = checkAuthor(u, authors, options.authorDefinition);
|
|
79
|
+
if (!author.ok)
|
|
80
|
+
return author;
|
|
81
|
+
const { payer, definitionFromLedger } = author.value;
|
|
82
|
+
const roles = checkPayer(payer, expect);
|
|
83
|
+
if (!roles.ok)
|
|
84
|
+
return roles;
|
|
85
|
+
const payments = checkMessages(messages, expect);
|
|
86
|
+
if (!payments.ok)
|
|
87
|
+
return payments;
|
|
88
|
+
const transfers = checkTransfers(payments.value, payer, expect);
|
|
89
|
+
if (!transfers.ok)
|
|
90
|
+
return transfers;
|
|
91
|
+
const commissions = expectedCommissions(u);
|
|
92
|
+
if (commissions.headers !== u['headers_commission'] ||
|
|
93
|
+
commissions.payload !== u['payload_commission']) {
|
|
94
|
+
return reject(EXACT_REASONS.commissions, 'Commissions do not match the unit size');
|
|
95
|
+
}
|
|
96
|
+
return accept({
|
|
97
|
+
unitHash,
|
|
98
|
+
payer,
|
|
99
|
+
inputs: transfers.value.inputs,
|
|
100
|
+
lastBallUnit: u['last_ball_unit'],
|
|
101
|
+
parentUnits: u['parent_units'],
|
|
102
|
+
timestamp: u['timestamp'],
|
|
103
|
+
outputTotals: transfers.value.outputTotals,
|
|
104
|
+
commissions,
|
|
105
|
+
definitionFromLedger,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
const unsupported = (why) => reject(EXACT_REASONS.unsupported, why);
|
|
109
|
+
/** Structure, size, network and header fields. */
|
|
110
|
+
function checkShape(unit, expect) {
|
|
71
111
|
if (!isPlainObject(unit))
|
|
72
112
|
return unsupported('Unit must be an object');
|
|
73
113
|
let serialized;
|
|
@@ -78,16 +118,14 @@ export function validateExactUnit(unit, expect, options = {}) {
|
|
|
78
118
|
return unsupported('Unit is not serializable');
|
|
79
119
|
}
|
|
80
120
|
if (serialized.length > (expect.maxUnitBytes ?? DEFAULT_MAX_UNIT_BYTES)) {
|
|
81
|
-
return reject(
|
|
121
|
+
return reject(EXACT_REASONS.tooLarge, 'Unit exceeds the size limit');
|
|
82
122
|
}
|
|
83
123
|
if (!hasOnlyKeys(unit, UNIT_KEYS))
|
|
84
124
|
return unsupported('Unit has fields outside the profile');
|
|
85
|
-
// --- network --------------------------------------------------------------
|
|
86
125
|
const net = expect.network.name;
|
|
87
126
|
if (unit['version'] !== EXACT_UNIT_VERSIONS[net] || unit['alt'] !== ALT[net]) {
|
|
88
|
-
return reject(
|
|
127
|
+
return reject(EXACT_REASONS.network, `Unit version/alt do not match ${expect.network.caip2}`);
|
|
89
128
|
}
|
|
90
|
-
// --- headers --------------------------------------------------------------
|
|
91
129
|
const parents = unit['parent_units'];
|
|
92
130
|
if (!Array.isArray(parents) || parents.length === 0 || !parents.every(isHash)) {
|
|
93
131
|
return unsupported('Invalid parent_units');
|
|
@@ -106,9 +144,12 @@ export function validateExactUnit(unit, expect, options = {}) {
|
|
|
106
144
|
if (fee in unit && !isIndex(unit[fee]))
|
|
107
145
|
return unsupported(`Invalid ${fee}`);
|
|
108
146
|
}
|
|
109
|
-
|
|
147
|
+
return accept(unit);
|
|
148
|
+
}
|
|
149
|
+
/** The unit hash is present and matches the content. */
|
|
150
|
+
function checkUnitHash(unit) {
|
|
110
151
|
if (!isHash(unit['unit']))
|
|
111
|
-
return reject(
|
|
152
|
+
return reject(EXACT_REASONS.unitHash, 'Missing unit hash');
|
|
112
153
|
const messages = unit['messages'];
|
|
113
154
|
const authors = unit['authors'];
|
|
114
155
|
if (!Array.isArray(messages) || !Array.isArray(authors))
|
|
@@ -118,37 +159,33 @@ export function validateExactUnit(unit, expect, options = {}) {
|
|
|
118
159
|
unitHash = getUnitHash(unit);
|
|
119
160
|
}
|
|
120
161
|
catch {
|
|
121
|
-
return reject(
|
|
162
|
+
return reject(EXACT_REASONS.unitHash, 'Unit cannot be hashed');
|
|
163
|
+
}
|
|
164
|
+
if (unitHash !== unit['unit']) {
|
|
165
|
+
return reject(EXACT_REASONS.unitHash, 'Unit hash does not match content');
|
|
122
166
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
167
|
+
return accept({ unitHash, messages, authors });
|
|
168
|
+
}
|
|
169
|
+
/** One author with a single-sig definition (embedded or from the ledger) and a valid signature. */
|
|
170
|
+
function checkAuthor(unit, authors, ledgerDefinition) {
|
|
171
|
+
const R = EXACT_REASONS;
|
|
126
172
|
if (authors.length !== 1)
|
|
127
173
|
return unsupported('Exactly one author is supported');
|
|
128
174
|
const author = authors[0];
|
|
129
|
-
if (!isPlainObject(author) || !hasOnlyKeys(author, AUTHOR_KEYS))
|
|
175
|
+
if (!isPlainObject(author) || !hasOnlyKeys(author, AUTHOR_KEYS)) {
|
|
130
176
|
return unsupported('Malformed author');
|
|
177
|
+
}
|
|
131
178
|
const payer = author['address'];
|
|
132
179
|
if (!isAddress(payer))
|
|
133
180
|
return unsupported('Invalid author address');
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
if (
|
|
137
|
-
if (!isSigDefinition(author['definition'])) {
|
|
138
|
-
return reject(R.definition, "Only ['sig', {pubkey}] author definitions are supported");
|
|
139
|
-
}
|
|
140
|
-
definition = author['definition'];
|
|
141
|
-
}
|
|
142
|
-
else if (options.authorDefinition !== undefined) {
|
|
143
|
-
if (!isSigDefinition(options.authorDefinition)) {
|
|
144
|
-
return reject(R.definition, "Only ['sig', {pubkey}] author definitions are supported");
|
|
145
|
-
}
|
|
146
|
-
definition = options.authorDefinition;
|
|
147
|
-
definitionFromLedger = true;
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
181
|
+
const embedded = 'definition' in author;
|
|
182
|
+
const definition = embedded ? author['definition'] : ledgerDefinition;
|
|
183
|
+
if (definition === undefined) {
|
|
150
184
|
return reject(R.definitionRequired, 'Author definition is not embedded; fetch it from the ledger');
|
|
151
185
|
}
|
|
186
|
+
if (!isSigDefinition(definition)) {
|
|
187
|
+
return reject(R.definition, "Only ['sig', {pubkey}] author definitions are supported");
|
|
188
|
+
}
|
|
152
189
|
if (obyte.utils.getChash160([...definition]) !== payer) {
|
|
153
190
|
return reject(R.definition, 'Definition does not match the author address');
|
|
154
191
|
}
|
|
@@ -159,13 +196,23 @@ export function validateExactUnit(unit, expect, options = {}) {
|
|
|
159
196
|
if (!verifySignature(getUnitHashToSign(unit), authentifiers['r'], definition[1].pubkey)) {
|
|
160
197
|
return reject(R.signature, 'Signature is invalid');
|
|
161
198
|
}
|
|
162
|
-
|
|
199
|
+
return accept({ payer, definitionFromLedger: !embedded });
|
|
200
|
+
}
|
|
201
|
+
/** The payer is neither the recipient nor the facilitator. */
|
|
202
|
+
function checkPayer(payer, expect) {
|
|
163
203
|
if (payer === expect.payTo)
|
|
164
|
-
return reject(
|
|
204
|
+
return reject(EXACT_REASONS.payer, 'Payer and payTo must differ');
|
|
165
205
|
if (expect.facilitatorAddresses?.includes(payer)) {
|
|
166
|
-
return reject(
|
|
206
|
+
return reject(EXACT_REASONS.payer, 'A facilitator address must never be the payer');
|
|
167
207
|
}
|
|
168
|
-
|
|
208
|
+
return accept(null);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Inline messages with matching hashes: exactly one data message carrying the
|
|
212
|
+
* binding, one payment per asset, bytes always and only the expected asset besides.
|
|
213
|
+
*/
|
|
214
|
+
function checkMessages(messages, expect) {
|
|
215
|
+
const R = EXACT_REASONS;
|
|
169
216
|
let dataCount = 0;
|
|
170
217
|
const payments = new Map();
|
|
171
218
|
for (const message of messages) {
|
|
@@ -186,34 +233,49 @@ export function validateExactUnit(unit, expect, options = {}) {
|
|
|
186
233
|
return binding;
|
|
187
234
|
}
|
|
188
235
|
else if (message['app'] === 'payment') {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
if (asset === 'base' && 'asset' in payload)
|
|
194
|
-
return unsupported('Bytes payment must omit asset');
|
|
195
|
-
if (!isAssetId(asset))
|
|
196
|
-
return unsupported('Invalid payment asset');
|
|
197
|
-
if (payments.has(asset))
|
|
236
|
+
const asset = paymentAsset(payload);
|
|
237
|
+
if (!asset.ok)
|
|
238
|
+
return asset;
|
|
239
|
+
if (payments.has(asset.value))
|
|
198
240
|
return unsupported('One payment message per asset');
|
|
199
|
-
payments.set(asset, payload);
|
|
241
|
+
payments.set(asset.value, payload);
|
|
200
242
|
}
|
|
201
243
|
else {
|
|
202
244
|
return unsupported('Only payment and data messages are supported');
|
|
203
245
|
}
|
|
204
246
|
}
|
|
205
|
-
if (dataCount !== 1)
|
|
247
|
+
if (dataCount !== 1) {
|
|
206
248
|
return reject(R.binding, 'Exactly one data message with the binding is required');
|
|
249
|
+
}
|
|
207
250
|
if (!payments.has('base'))
|
|
208
251
|
return unsupported('A bytes payment message is required');
|
|
209
|
-
const allowedAssets = new Set(['base', expect.asset]);
|
|
210
252
|
for (const asset of payments.keys()) {
|
|
211
|
-
if (
|
|
253
|
+
if (asset !== 'base' && asset !== expect.asset) {
|
|
212
254
|
return reject(R.asset, 'Payment in an unexpected asset');
|
|
255
|
+
}
|
|
213
256
|
}
|
|
214
257
|
if (!payments.has(expect.asset))
|
|
215
258
|
return reject(R.asset, 'No payment in the required asset');
|
|
216
|
-
|
|
259
|
+
return accept(payments);
|
|
260
|
+
}
|
|
261
|
+
/** The asset of a payment message ('base' when omitted). */
|
|
262
|
+
function paymentAsset(payload) {
|
|
263
|
+
if (!isPlainObject(payload) || !hasOnlyKeys(payload, PAYMENT_KEYS)) {
|
|
264
|
+
return unsupported('Malformed payment');
|
|
265
|
+
}
|
|
266
|
+
const asset = 'asset' in payload ? payload['asset'] : 'base';
|
|
267
|
+
if (asset === 'base' && 'asset' in payload)
|
|
268
|
+
return unsupported('Bytes payment must omit asset');
|
|
269
|
+
if (!isAssetId(asset))
|
|
270
|
+
return unsupported('Invalid payment asset');
|
|
271
|
+
return accept(asset);
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Transfer inputs only (no duplicates); sorted outputs that go to payTo
|
|
275
|
+
* (exactly once, the exact amount, the expected asset) or back to the payer.
|
|
276
|
+
*/
|
|
277
|
+
function checkTransfers(payments, payer, expect) {
|
|
278
|
+
const R = EXACT_REASONS;
|
|
217
279
|
const inputs = [];
|
|
218
280
|
const seenInputs = new Set();
|
|
219
281
|
const outputTotals = {};
|
|
@@ -226,23 +288,14 @@ export function validateExactUnit(unit, expect, options = {}) {
|
|
|
226
288
|
return unsupported('Payment needs inputs and outputs');
|
|
227
289
|
}
|
|
228
290
|
for (const input of ins) {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
!isHash(input['unit']) ||
|
|
232
|
-
!isIndex(input['message_index']) ||
|
|
233
|
-
!isIndex(input['output_index'])) {
|
|
291
|
+
const ref = transferInput(input, asset);
|
|
292
|
+
if (ref === undefined)
|
|
234
293
|
return unsupported('Only transfer inputs are supported');
|
|
235
|
-
}
|
|
236
|
-
const key = `${input['unit']}:${input['message_index']}:${input['output_index']}`;
|
|
294
|
+
const key = `${ref.unit}:${ref.messageIndex}:${ref.outputIndex}`;
|
|
237
295
|
if (seenInputs.has(key))
|
|
238
296
|
return unsupported('Duplicate input');
|
|
239
297
|
seenInputs.add(key);
|
|
240
|
-
inputs.push(
|
|
241
|
-
asset,
|
|
242
|
-
unit: input['unit'],
|
|
243
|
-
messageIndex: input['message_index'],
|
|
244
|
-
outputIndex: input['output_index'],
|
|
245
|
-
});
|
|
298
|
+
inputs.push(ref);
|
|
246
299
|
}
|
|
247
300
|
let total = 0n;
|
|
248
301
|
let previous;
|
|
@@ -260,15 +313,14 @@ export function validateExactUnit(unit, expect, options = {}) {
|
|
|
260
313
|
return unsupported('Outputs must be sorted by address and amount without duplicates');
|
|
261
314
|
}
|
|
262
315
|
previous = current;
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
if (output['address'] === expect.payTo) {
|
|
316
|
+
total += BigInt(current.amount);
|
|
317
|
+
if (current.address === expect.payTo) {
|
|
266
318
|
if (asset !== expect.asset)
|
|
267
319
|
return reject(R.recipient, 'payTo receives an unexpected asset');
|
|
268
320
|
outputsToPayTo += 1;
|
|
269
|
-
paidToPayTo += amount;
|
|
321
|
+
paidToPayTo += BigInt(current.amount);
|
|
270
322
|
}
|
|
271
|
-
else if (
|
|
323
|
+
else if (current.address !== payer) {
|
|
272
324
|
return reject(R.recipient, 'Outputs may only go to payTo or back to the payer');
|
|
273
325
|
}
|
|
274
326
|
}
|
|
@@ -278,23 +330,23 @@ export function validateExactUnit(unit, expect, options = {}) {
|
|
|
278
330
|
return reject(R.recipient, 'Exactly one output to payTo is required');
|
|
279
331
|
if (paidToPayTo !== expect.amount)
|
|
280
332
|
return reject(R.amount, 'Amount paid to payTo does not match');
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
333
|
+
return accept({ inputs, outputTotals });
|
|
334
|
+
}
|
|
335
|
+
/** A transfer input (unit, message_index, output_index), or undefined for anything else. */
|
|
336
|
+
function transferInput(input, asset) {
|
|
337
|
+
if (!isPlainObject(input) ||
|
|
338
|
+
!hasOnlyKeys(input, INPUT_KEYS) ||
|
|
339
|
+
!isHash(input['unit']) ||
|
|
340
|
+
!isIndex(input['message_index']) ||
|
|
341
|
+
!isIndex(input['output_index'])) {
|
|
342
|
+
return undefined;
|
|
286
343
|
}
|
|
287
|
-
return
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
timestamp: unit['timestamp'],
|
|
294
|
-
outputTotals,
|
|
295
|
-
commissions,
|
|
296
|
-
definitionFromLedger,
|
|
297
|
-
});
|
|
344
|
+
return {
|
|
345
|
+
asset,
|
|
346
|
+
unit: input['unit'],
|
|
347
|
+
messageIndex: input['message_index'],
|
|
348
|
+
outputIndex: input['output_index'],
|
|
349
|
+
};
|
|
298
350
|
}
|
|
299
351
|
/** Length of one base64 secp256k1 signature, as counted by obyte.js. */
|
|
300
352
|
const SIGNATURE_SIZE = 88;
|
|
@@ -317,6 +369,7 @@ export function compareOutputs(a, b) {
|
|
|
317
369
|
return a.address < b.address ? -1 : 1;
|
|
318
370
|
return a.amount - b.amount;
|
|
319
371
|
}
|
|
372
|
+
/** The data message is exactly `{x402: {binding, quoteId}}` of this operation (undefined when it is). */
|
|
320
373
|
function checkBinding(payload, expect) {
|
|
321
374
|
const R = EXACT_REASONS;
|
|
322
375
|
if (!isPlainObject(payload) || !hasOnlyKeys(payload, new Set(['x402']))) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exact-unit.js","sourceRoot":"","sources":["../../src/unit/exact-unit.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"exact-unit.js","sourceRoot":"","sources":["../../src/unit/exact-unit.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/unit/exact-unit.ts
CHANGED
|
@@ -117,10 +117,47 @@ export function validateExactUnit(
|
|
|
117
117
|
expect: ExactExpectation,
|
|
118
118
|
options: { authorDefinition?: SigDefinition } = {},
|
|
119
119
|
): Verdict<ExactUnitFacts> {
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
// The order of the checks is part of the contract: the first failing one
|
|
121
|
+
// decides the reason code.
|
|
122
|
+
const shaped = checkShape(unit, expect);
|
|
123
|
+
if (!shaped.ok) return shaped;
|
|
124
|
+
const u = shaped.value;
|
|
125
|
+
const hashed = checkUnitHash(u);
|
|
126
|
+
if (!hashed.ok) return hashed;
|
|
127
|
+
const { unitHash, messages, authors } = hashed.value;
|
|
128
|
+
const author = checkAuthor(u, authors, options.authorDefinition);
|
|
129
|
+
if (!author.ok) return author;
|
|
130
|
+
const { payer, definitionFromLedger } = author.value;
|
|
131
|
+
const roles = checkPayer(payer, expect);
|
|
132
|
+
if (!roles.ok) return roles;
|
|
133
|
+
const payments = checkMessages(messages, expect);
|
|
134
|
+
if (!payments.ok) return payments;
|
|
135
|
+
const transfers = checkTransfers(payments.value, payer, expect);
|
|
136
|
+
if (!transfers.ok) return transfers;
|
|
137
|
+
const commissions = expectedCommissions(u);
|
|
138
|
+
if (
|
|
139
|
+
commissions.headers !== u['headers_commission'] ||
|
|
140
|
+
commissions.payload !== u['payload_commission']
|
|
141
|
+
) {
|
|
142
|
+
return reject(EXACT_REASONS.commissions, 'Commissions do not match the unit size');
|
|
143
|
+
}
|
|
144
|
+
return accept({
|
|
145
|
+
unitHash,
|
|
146
|
+
payer,
|
|
147
|
+
inputs: transfers.value.inputs,
|
|
148
|
+
lastBallUnit: u['last_ball_unit'] as string,
|
|
149
|
+
parentUnits: u['parent_units'] as string[],
|
|
150
|
+
timestamp: u['timestamp'] as number,
|
|
151
|
+
outputTotals: transfers.value.outputTotals,
|
|
152
|
+
commissions,
|
|
153
|
+
definitionFromLedger,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const unsupported = (why: string) => reject<never>(EXACT_REASONS.unsupported, why);
|
|
122
158
|
|
|
123
|
-
|
|
159
|
+
/** Structure, size, network and header fields. */
|
|
160
|
+
function checkShape(unit: unknown, expect: ExactExpectation): Verdict<Record<string, unknown>> {
|
|
124
161
|
if (!isPlainObject(unit)) return unsupported('Unit must be an object');
|
|
125
162
|
let serialized: string;
|
|
126
163
|
try {
|
|
@@ -129,17 +166,15 @@ export function validateExactUnit(
|
|
|
129
166
|
return unsupported('Unit is not serializable');
|
|
130
167
|
}
|
|
131
168
|
if (serialized.length > (expect.maxUnitBytes ?? DEFAULT_MAX_UNIT_BYTES)) {
|
|
132
|
-
return reject(
|
|
169
|
+
return reject(EXACT_REASONS.tooLarge, 'Unit exceeds the size limit');
|
|
133
170
|
}
|
|
134
171
|
if (!hasOnlyKeys(unit, UNIT_KEYS)) return unsupported('Unit has fields outside the profile');
|
|
135
172
|
|
|
136
|
-
// --- network --------------------------------------------------------------
|
|
137
173
|
const net = expect.network.name;
|
|
138
174
|
if (unit['version'] !== EXACT_UNIT_VERSIONS[net] || unit['alt'] !== ALT[net]) {
|
|
139
|
-
return reject(
|
|
175
|
+
return reject(EXACT_REASONS.network, `Unit version/alt do not match ${expect.network.caip2}`);
|
|
140
176
|
}
|
|
141
177
|
|
|
142
|
-
// --- headers --------------------------------------------------------------
|
|
143
178
|
const parents = unit['parent_units'];
|
|
144
179
|
if (!Array.isArray(parents) || parents.length === 0 || !parents.every(isHash)) {
|
|
145
180
|
return unsupported('Invalid parent_units');
|
|
@@ -156,9 +191,14 @@ export function validateExactUnit(
|
|
|
156
191
|
for (const fee of ['tps_fee', 'burn_fee', 'max_aa_responses'] as const) {
|
|
157
192
|
if (fee in unit && !isIndex(unit[fee])) return unsupported(`Invalid ${fee}`);
|
|
158
193
|
}
|
|
194
|
+
return accept(unit);
|
|
195
|
+
}
|
|
159
196
|
|
|
160
|
-
|
|
161
|
-
|
|
197
|
+
/** The unit hash is present and matches the content. */
|
|
198
|
+
function checkUnitHash(
|
|
199
|
+
unit: Record<string, unknown>,
|
|
200
|
+
): Verdict<{ unitHash: string; messages: unknown[]; authors: unknown[] }> {
|
|
201
|
+
if (!isHash(unit['unit'])) return reject(EXACT_REASONS.unitHash, 'Missing unit hash');
|
|
162
202
|
const messages = unit['messages'];
|
|
163
203
|
const authors = unit['authors'];
|
|
164
204
|
if (!Array.isArray(messages) || !Array.isArray(authors)) return unsupported('Malformed unit');
|
|
@@ -166,37 +206,40 @@ export function validateExactUnit(
|
|
|
166
206
|
try {
|
|
167
207
|
unitHash = getUnitHash(unit);
|
|
168
208
|
} catch {
|
|
169
|
-
return reject(
|
|
209
|
+
return reject(EXACT_REASONS.unitHash, 'Unit cannot be hashed');
|
|
170
210
|
}
|
|
171
|
-
if (unitHash !== unit['unit'])
|
|
211
|
+
if (unitHash !== unit['unit']) {
|
|
212
|
+
return reject(EXACT_REASONS.unitHash, 'Unit hash does not match content');
|
|
213
|
+
}
|
|
214
|
+
return accept({ unitHash, messages, authors });
|
|
215
|
+
}
|
|
172
216
|
|
|
173
|
-
|
|
217
|
+
/** One author with a single-sig definition (embedded or from the ledger) and a valid signature. */
|
|
218
|
+
function checkAuthor(
|
|
219
|
+
unit: Record<string, unknown>,
|
|
220
|
+
authors: unknown[],
|
|
221
|
+
ledgerDefinition: SigDefinition | undefined,
|
|
222
|
+
): Verdict<{ payer: string; definitionFromLedger: boolean }> {
|
|
223
|
+
const R = EXACT_REASONS;
|
|
174
224
|
if (authors.length !== 1) return unsupported('Exactly one author is supported');
|
|
175
225
|
const author: unknown = authors[0];
|
|
176
|
-
if (!isPlainObject(author) || !hasOnlyKeys(author, AUTHOR_KEYS))
|
|
226
|
+
if (!isPlainObject(author) || !hasOnlyKeys(author, AUTHOR_KEYS)) {
|
|
177
227
|
return unsupported('Malformed author');
|
|
228
|
+
}
|
|
178
229
|
const payer = author['address'];
|
|
179
230
|
if (!isAddress(payer)) return unsupported('Invalid author address');
|
|
180
231
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
if (
|
|
184
|
-
if (!isSigDefinition(author['definition'])) {
|
|
185
|
-
return reject(R.definition, "Only ['sig', {pubkey}] author definitions are supported");
|
|
186
|
-
}
|
|
187
|
-
definition = author['definition'];
|
|
188
|
-
} else if (options.authorDefinition !== undefined) {
|
|
189
|
-
if (!isSigDefinition(options.authorDefinition)) {
|
|
190
|
-
return reject(R.definition, "Only ['sig', {pubkey}] author definitions are supported");
|
|
191
|
-
}
|
|
192
|
-
definition = options.authorDefinition;
|
|
193
|
-
definitionFromLedger = true;
|
|
194
|
-
} else {
|
|
232
|
+
const embedded = 'definition' in author;
|
|
233
|
+
const definition: unknown = embedded ? author['definition'] : ledgerDefinition;
|
|
234
|
+
if (definition === undefined) {
|
|
195
235
|
return reject(
|
|
196
236
|
R.definitionRequired,
|
|
197
237
|
'Author definition is not embedded; fetch it from the ledger',
|
|
198
238
|
);
|
|
199
239
|
}
|
|
240
|
+
if (!isSigDefinition(definition)) {
|
|
241
|
+
return reject(R.definition, "Only ['sig', {pubkey}] author definitions are supported");
|
|
242
|
+
}
|
|
200
243
|
if (obyte.utils.getChash160([...definition]) !== payer) {
|
|
201
244
|
return reject(R.definition, 'Definition does not match the author address');
|
|
202
245
|
}
|
|
@@ -207,14 +250,27 @@ export function validateExactUnit(
|
|
|
207
250
|
if (!verifySignature(getUnitHashToSign(unit), authentifiers['r'], definition[1].pubkey)) {
|
|
208
251
|
return reject(R.signature, 'Signature is invalid');
|
|
209
252
|
}
|
|
253
|
+
return accept({ payer, definitionFromLedger: !embedded });
|
|
254
|
+
}
|
|
210
255
|
|
|
211
|
-
|
|
212
|
-
|
|
256
|
+
/** The payer is neither the recipient nor the facilitator. */
|
|
257
|
+
function checkPayer(payer: string, expect: ExactExpectation): Verdict<null> {
|
|
258
|
+
if (payer === expect.payTo) return reject(EXACT_REASONS.payer, 'Payer and payTo must differ');
|
|
213
259
|
if (expect.facilitatorAddresses?.includes(payer)) {
|
|
214
|
-
return reject(
|
|
260
|
+
return reject(EXACT_REASONS.payer, 'A facilitator address must never be the payer');
|
|
215
261
|
}
|
|
262
|
+
return accept(null);
|
|
263
|
+
}
|
|
216
264
|
|
|
217
|
-
|
|
265
|
+
/**
|
|
266
|
+
* Inline messages with matching hashes: exactly one data message carrying the
|
|
267
|
+
* binding, one payment per asset, bytes always and only the expected asset besides.
|
|
268
|
+
*/
|
|
269
|
+
function checkMessages(
|
|
270
|
+
messages: unknown[],
|
|
271
|
+
expect: ExactExpectation,
|
|
272
|
+
): Verdict<Map<string, Record<string, unknown>>> {
|
|
273
|
+
const R = EXACT_REASONS;
|
|
218
274
|
let dataCount = 0;
|
|
219
275
|
const payments = new Map<string, Record<string, unknown>>();
|
|
220
276
|
for (const message of messages) {
|
|
@@ -233,29 +289,48 @@ export function validateExactUnit(
|
|
|
233
289
|
const binding = checkBinding(payload, expect);
|
|
234
290
|
if (binding !== undefined) return binding;
|
|
235
291
|
} else if (message['app'] === 'payment') {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
if (asset === 'base' && 'asset' in payload)
|
|
241
|
-
return unsupported('Bytes payment must omit asset');
|
|
242
|
-
if (!isAssetId(asset)) return unsupported('Invalid payment asset');
|
|
243
|
-
if (payments.has(asset)) return unsupported('One payment message per asset');
|
|
244
|
-
payments.set(asset, payload);
|
|
292
|
+
const asset = paymentAsset(payload);
|
|
293
|
+
if (!asset.ok) return asset;
|
|
294
|
+
if (payments.has(asset.value)) return unsupported('One payment message per asset');
|
|
295
|
+
payments.set(asset.value, payload as Record<string, unknown>);
|
|
245
296
|
} else {
|
|
246
297
|
return unsupported('Only payment and data messages are supported');
|
|
247
298
|
}
|
|
248
299
|
}
|
|
249
|
-
if (dataCount !== 1)
|
|
300
|
+
if (dataCount !== 1) {
|
|
250
301
|
return reject(R.binding, 'Exactly one data message with the binding is required');
|
|
302
|
+
}
|
|
251
303
|
if (!payments.has('base')) return unsupported('A bytes payment message is required');
|
|
252
|
-
const allowedAssets = new Set(['base', expect.asset]);
|
|
253
304
|
for (const asset of payments.keys()) {
|
|
254
|
-
if (
|
|
305
|
+
if (asset !== 'base' && asset !== expect.asset) {
|
|
306
|
+
return reject(R.asset, 'Payment in an unexpected asset');
|
|
307
|
+
}
|
|
255
308
|
}
|
|
256
309
|
if (!payments.has(expect.asset)) return reject(R.asset, 'No payment in the required asset');
|
|
310
|
+
return accept(payments);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/** The asset of a payment message ('base' when omitted). */
|
|
314
|
+
function paymentAsset(payload: unknown): Verdict<string> {
|
|
315
|
+
if (!isPlainObject(payload) || !hasOnlyKeys(payload, PAYMENT_KEYS)) {
|
|
316
|
+
return unsupported('Malformed payment');
|
|
317
|
+
}
|
|
318
|
+
const asset = 'asset' in payload ? payload['asset'] : 'base';
|
|
319
|
+
if (asset === 'base' && 'asset' in payload) return unsupported('Bytes payment must omit asset');
|
|
320
|
+
if (!isAssetId(asset)) return unsupported('Invalid payment asset');
|
|
321
|
+
return accept(asset);
|
|
322
|
+
}
|
|
257
323
|
|
|
258
|
-
|
|
324
|
+
/**
|
|
325
|
+
* Transfer inputs only (no duplicates); sorted outputs that go to payTo
|
|
326
|
+
* (exactly once, the exact amount, the expected asset) or back to the payer.
|
|
327
|
+
*/
|
|
328
|
+
function checkTransfers(
|
|
329
|
+
payments: Map<string, Record<string, unknown>>,
|
|
330
|
+
payer: string,
|
|
331
|
+
expect: ExactExpectation,
|
|
332
|
+
): Verdict<{ inputs: InputRef[]; outputTotals: Record<string, bigint> }> {
|
|
333
|
+
const R = EXACT_REASONS;
|
|
259
334
|
const inputs: InputRef[] = [];
|
|
260
335
|
const seenInputs = new Set<string>();
|
|
261
336
|
const outputTotals: Record<string, bigint> = {};
|
|
@@ -268,24 +343,12 @@ export function validateExactUnit(
|
|
|
268
343
|
return unsupported('Payment needs inputs and outputs');
|
|
269
344
|
}
|
|
270
345
|
for (const input of ins) {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
!isHash(input['unit']) ||
|
|
275
|
-
!isIndex(input['message_index']) ||
|
|
276
|
-
!isIndex(input['output_index'])
|
|
277
|
-
) {
|
|
278
|
-
return unsupported('Only transfer inputs are supported');
|
|
279
|
-
}
|
|
280
|
-
const key = `${input['unit']}:${input['message_index']}:${input['output_index']}`;
|
|
346
|
+
const ref = transferInput(input, asset);
|
|
347
|
+
if (ref === undefined) return unsupported('Only transfer inputs are supported');
|
|
348
|
+
const key = `${ref.unit}:${ref.messageIndex}:${ref.outputIndex}`;
|
|
281
349
|
if (seenInputs.has(key)) return unsupported('Duplicate input');
|
|
282
350
|
seenInputs.add(key);
|
|
283
|
-
inputs.push(
|
|
284
|
-
asset,
|
|
285
|
-
unit: input['unit'],
|
|
286
|
-
messageIndex: input['message_index'],
|
|
287
|
-
outputIndex: input['output_index'],
|
|
288
|
-
});
|
|
351
|
+
inputs.push(ref);
|
|
289
352
|
}
|
|
290
353
|
let total = 0n;
|
|
291
354
|
let previous: { address: string; amount: number } | undefined;
|
|
@@ -305,14 +368,13 @@ export function validateExactUnit(
|
|
|
305
368
|
return unsupported('Outputs must be sorted by address and amount without duplicates');
|
|
306
369
|
}
|
|
307
370
|
previous = current;
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
if (output['address'] === expect.payTo) {
|
|
371
|
+
total += BigInt(current.amount);
|
|
372
|
+
if (current.address === expect.payTo) {
|
|
311
373
|
if (asset !== expect.asset)
|
|
312
374
|
return reject(R.recipient, 'payTo receives an unexpected asset');
|
|
313
375
|
outputsToPayTo += 1;
|
|
314
|
-
paidToPayTo += amount;
|
|
315
|
-
} else if (
|
|
376
|
+
paidToPayTo += BigInt(current.amount);
|
|
377
|
+
} else if (current.address !== payer) {
|
|
316
378
|
return reject(R.recipient, 'Outputs may only go to payTo or back to the payer');
|
|
317
379
|
}
|
|
318
380
|
}
|
|
@@ -320,27 +382,26 @@ export function validateExactUnit(
|
|
|
320
382
|
}
|
|
321
383
|
if (outputsToPayTo !== 1) return reject(R.recipient, 'Exactly one output to payTo is required');
|
|
322
384
|
if (paidToPayTo !== expect.amount) return reject(R.amount, 'Amount paid to payTo does not match');
|
|
385
|
+
return accept({ inputs, outputTotals });
|
|
386
|
+
}
|
|
323
387
|
|
|
324
|
-
|
|
325
|
-
|
|
388
|
+
/** A transfer input (unit, message_index, output_index), or undefined for anything else. */
|
|
389
|
+
function transferInput(input: unknown, asset: string): InputRef | undefined {
|
|
326
390
|
if (
|
|
327
|
-
|
|
328
|
-
|
|
391
|
+
!isPlainObject(input) ||
|
|
392
|
+
!hasOnlyKeys(input, INPUT_KEYS) ||
|
|
393
|
+
!isHash(input['unit']) ||
|
|
394
|
+
!isIndex(input['message_index']) ||
|
|
395
|
+
!isIndex(input['output_index'])
|
|
329
396
|
) {
|
|
330
|
-
return
|
|
397
|
+
return undefined;
|
|
331
398
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
parentUnits: parents,
|
|
339
|
-
timestamp: unit['timestamp'] as number,
|
|
340
|
-
outputTotals,
|
|
341
|
-
commissions,
|
|
342
|
-
definitionFromLedger,
|
|
343
|
-
});
|
|
399
|
+
return {
|
|
400
|
+
asset,
|
|
401
|
+
unit: input['unit'],
|
|
402
|
+
messageIndex: input['message_index'],
|
|
403
|
+
outputIndex: input['output_index'],
|
|
404
|
+
};
|
|
344
405
|
}
|
|
345
406
|
|
|
346
407
|
/** Length of one base64 secp256k1 signature, as counted by obyte.js. */
|
|
@@ -369,10 +430,8 @@ export function compareOutputs(
|
|
|
369
430
|
return a.amount - b.amount;
|
|
370
431
|
}
|
|
371
432
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
expect: ExactExpectation,
|
|
375
|
-
): Verdict<ExactUnitFacts> | undefined {
|
|
433
|
+
/** The data message is exactly `{x402: {binding, quoteId}}` of this operation (undefined when it is). */
|
|
434
|
+
function checkBinding(payload: unknown, expect: ExactExpectation): Verdict<never> | undefined {
|
|
376
435
|
const R = EXACT_REASONS;
|
|
377
436
|
if (!isPlainObject(payload) || !hasOnlyKeys(payload, new Set(['x402']))) {
|
|
378
437
|
return reject(R.binding, 'Data message must be exactly {x402: {binding, quoteId}}');
|