@ocap/tx-pipeline 1.30.2 → 1.30.4
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/esm/helpers/encode-tx-by-context.d.mts +10 -0
- package/esm/helpers/encode-tx-by-context.mjs +16 -0
- package/esm/helpers/unwrap-opaque-any.d.mts +17 -0
- package/esm/helpers/unwrap-opaque-any.mjs +19 -0
- package/esm/pipes/decode-itx.mjs +53 -6
- package/esm/pipes/decode-tx.mjs +19 -3
- package/esm/pipes/verify-multisig-v2.mjs +8 -11
- package/esm/pipes/verify-multisig.mjs +10 -13
- package/esm/pipes/verify-signature.mjs +5 -8
- package/esm/pipes/verify-tx-size.mjs +3 -1
- package/esm/pipes/verify-tx.mjs +4 -1
- package/lib/helpers/encode-tx-by-context.cjs +17 -0
- package/lib/helpers/encode-tx-by-context.d.cts +10 -0
- package/lib/helpers/unwrap-opaque-any.cjs +20 -0
- package/lib/helpers/unwrap-opaque-any.d.cts +17 -0
- package/lib/pipes/decode-itx.cjs +52 -5
- package/lib/pipes/decode-tx.cjs +19 -3
- package/lib/pipes/verify-multisig-v2.cjs +6 -9
- package/lib/pipes/verify-multisig.cjs +8 -11
- package/lib/pipes/verify-signature.cjs +5 -8
- package/lib/pipes/verify-tx-size.cjs +3 -1
- package/lib/pipes/verify-tx.cjs +4 -1
- package/package.json +10 -10
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/helpers/encode-tx-by-context.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Pick the encoder matching `context.txEncoding`. Centralizes the ternary
|
|
4
|
+
* that lived in three verify pipes so future encoding additions touch one
|
|
5
|
+
* place. Chain-side only — client bundles that want tree-shake keep their
|
|
6
|
+
* local selection.
|
|
7
|
+
*/
|
|
8
|
+
declare function encodeTxByEncoding(encoding: string | undefined, tx: Record<string, unknown>): Uint8Array;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { encodeTxByEncoding };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { encodeTx } from "@ocap/message/cbor";
|
|
2
|
+
import { encodeTx as encodeTx$1 } from "@ocap/message/protobuf";
|
|
3
|
+
|
|
4
|
+
//#region src/helpers/encode-tx-by-context.ts
|
|
5
|
+
/**
|
|
6
|
+
* Pick the encoder matching `context.txEncoding`. Centralizes the ternary
|
|
7
|
+
* that lived in three verify pipes so future encoding additions touch one
|
|
8
|
+
* place. Chain-side only — client bundles that want tree-shake keep their
|
|
9
|
+
* local selection.
|
|
10
|
+
*/
|
|
11
|
+
function encodeTxByEncoding(encoding, tx) {
|
|
12
|
+
return encoding === "cbor" ? encodeTx(tx) : encodeTx$1(tx);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
//#endregion
|
|
16
|
+
export { encodeTxByEncoding };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/helpers/unwrap-opaque-any.d.ts
|
|
2
|
+
interface DecodedAny {
|
|
3
|
+
type?: string;
|
|
4
|
+
value?: unknown;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Undo the duplicate base64+JSON serialization that `decodeAny` leaves on
|
|
8
|
+
* `json` / `vc` typed Any payloads. Mutates `decoded.value` in place when
|
|
9
|
+
* applicable and is a no-op otherwise (including on malformed JSON — we
|
|
10
|
+
* swallow the parse error to keep legacy behavior).
|
|
11
|
+
*
|
|
12
|
+
* HACK carried forward from pre-Phase-43 multisig verifiers; kept in one
|
|
13
|
+
* place so the two verify pipes share the exact same fallback.
|
|
14
|
+
*/
|
|
15
|
+
declare function unwrapOpaqueAnyData(decoded: DecodedAny | undefined): DecodedAny | undefined;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { unwrapOpaqueAnyData };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/helpers/unwrap-opaque-any.ts
|
|
2
|
+
/**
|
|
3
|
+
* Undo the duplicate base64+JSON serialization that `decodeAny` leaves on
|
|
4
|
+
* `json` / `vc` typed Any payloads. Mutates `decoded.value` in place when
|
|
5
|
+
* applicable and is a no-op otherwise (including on malformed JSON — we
|
|
6
|
+
* swallow the parse error to keep legacy behavior).
|
|
7
|
+
*
|
|
8
|
+
* HACK carried forward from pre-Phase-43 multisig verifiers; kept in one
|
|
9
|
+
* place so the two verify pipes share the exact same fallback.
|
|
10
|
+
*/
|
|
11
|
+
function unwrapOpaqueAnyData(decoded) {
|
|
12
|
+
if (decoded?.type && ["json", "vc"].includes(decoded.type)) try {
|
|
13
|
+
decoded.value = JSON.parse(Buffer.from(decoded.value, "base64").toString());
|
|
14
|
+
} catch (_e) {}
|
|
15
|
+
return decoded;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
export { unwrapOpaqueAnyData };
|
package/esm/pipes/decode-itx.mjs
CHANGED
|
@@ -1,17 +1,64 @@
|
|
|
1
1
|
import { CustomError } from "@ocap/util/lib/error";
|
|
2
|
-
import { decodeAny } from "@ocap/message";
|
|
2
|
+
import { createMessage, decodeAny, fromTypeUrl, toTypeUrl } from "@ocap/message";
|
|
3
3
|
|
|
4
4
|
//#region src/pipes/decode-itx.ts
|
|
5
|
+
/**
|
|
6
|
+
* Normalize `tx.itx` to a `{ typeUrl, value }` pair across the three shapes
|
|
7
|
+
* that reach this pipe:
|
|
8
|
+
*
|
|
9
|
+
* protobuf wire → jspb Any.toObject() → `{ typeUrl, value: <base64-bytes> }`
|
|
10
|
+
* cbor wire → canonical-cbor flat Any → `{ typeUrl, ...inner }`
|
|
11
|
+
* client raw → pre-encoding object → `{ type, value: { ...inner } }`
|
|
12
|
+
*
|
|
13
|
+
* Downstream protocol schemas and pipes expect the jspb-shaped inner object
|
|
14
|
+
* (repeated fields carry the `xxxList` alias, bytes fields are base64 strings,
|
|
15
|
+
* BigUint wrappers are `{ value: Uint8Array }`). We round-trip the cbor /
|
|
16
|
+
* client-raw cases through `createMessage().toObject()` so downstream code
|
|
17
|
+
* sees a single, stable shape regardless of wire format.
|
|
18
|
+
*/
|
|
19
|
+
function toJspbObject(typeUrl, inner) {
|
|
20
|
+
const msg = createMessage(fromTypeUrl(typeUrl), inner);
|
|
21
|
+
return msg?.toObject ? msg.toObject() : inner;
|
|
22
|
+
}
|
|
23
|
+
function normalizeItx(raw) {
|
|
24
|
+
if (!raw || typeof raw !== "object") return null;
|
|
25
|
+
if (raw.typeUrl) {
|
|
26
|
+
if (typeof raw.value === "string") {
|
|
27
|
+
const decoded = decodeAny(raw);
|
|
28
|
+
return {
|
|
29
|
+
typeUrl: raw.typeUrl,
|
|
30
|
+
value: decoded.value
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
const inner = {};
|
|
34
|
+
for (const [key, val] of Object.entries(raw)) {
|
|
35
|
+
if (key === "typeUrl" || key === "type_url") continue;
|
|
36
|
+
inner[key] = val;
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
typeUrl: raw.typeUrl,
|
|
40
|
+
value: toJspbObject(raw.typeUrl, inner)
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (raw.type) {
|
|
44
|
+
const typeUrl = toTypeUrl(raw.type);
|
|
45
|
+
return {
|
|
46
|
+
typeUrl,
|
|
47
|
+
value: toJspbObject(typeUrl, raw.value || {})
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
5
52
|
function DecodeItx(context, next) {
|
|
6
53
|
try {
|
|
7
|
-
const
|
|
8
|
-
|
|
54
|
+
const normalized = normalizeItx(context.tx.itx);
|
|
55
|
+
if (!normalized) return next(new CustomError("INVALID_TX", "Failed to decode itx"));
|
|
9
56
|
Object.defineProperty(context, "itx", {
|
|
10
|
-
value:
|
|
57
|
+
value: normalized.value,
|
|
11
58
|
enumerable: true
|
|
12
59
|
});
|
|
13
60
|
Object.defineProperty(context, "txType", {
|
|
14
|
-
value:
|
|
61
|
+
value: normalized.typeUrl,
|
|
15
62
|
enumerable: true
|
|
16
63
|
});
|
|
17
64
|
context.logger?.info("Tx decoded", {
|
|
@@ -19,7 +66,7 @@ function DecodeItx(context, next) {
|
|
|
19
66
|
txHash: context.txHash,
|
|
20
67
|
txTime: context.txTime,
|
|
21
68
|
txSize: context.txSize,
|
|
22
|
-
txType,
|
|
69
|
+
txType: normalized.typeUrl,
|
|
23
70
|
request: context.extra?.request
|
|
24
71
|
});
|
|
25
72
|
} catch (_err) {
|
package/esm/pipes/decode-tx.mjs
CHANGED
|
@@ -1,18 +1,34 @@
|
|
|
1
1
|
import { name } from "../package.mjs";
|
|
2
2
|
import { fromBase64, toUint8Array } from "@ocap/util";
|
|
3
3
|
import { CustomError } from "@ocap/util/lib/error";
|
|
4
|
-
import { getMessageType } from "@ocap/message";
|
|
5
4
|
import { toTxHash } from "@ocap/mcrypto";
|
|
5
|
+
import { CANONICAL_SELF_DESCRIBE_PREFIX, decodeTx } from "@ocap/message/cbor";
|
|
6
|
+
import { decodeTx as decodeTx$1 } from "@ocap/message/protobuf";
|
|
6
7
|
import Debug from "debug";
|
|
7
8
|
|
|
8
9
|
//#region src/pipes/decode-tx.ts
|
|
9
10
|
const debug = Debug(`${name}:pipe:decode-tx`);
|
|
10
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Detect the CBOR self-describe tag 55799 that our canonical encoder always
|
|
13
|
+
* prepends to a Transaction. The first three bytes are unambiguously distinct
|
|
14
|
+
* from any protobuf encoding of Transaction because `D9` = `(27 << 3) | 1`,
|
|
15
|
+
* and `Transaction` has no top-level field number ≥ 27 (enforced by
|
|
16
|
+
* `scripts/assert-proto-field-bound.ts`).
|
|
17
|
+
*/
|
|
18
|
+
function hasCborSelfDescribeTag(buf) {
|
|
19
|
+
return buf.length >= CANONICAL_SELF_DESCRIBE_PREFIX.length && buf[0] === CANONICAL_SELF_DESCRIBE_PREFIX[0] && buf[1] === CANONICAL_SELF_DESCRIBE_PREFIX[1] && buf[2] === CANONICAL_SELF_DESCRIBE_PREFIX[2];
|
|
20
|
+
}
|
|
11
21
|
function DecodeTx(context, next) {
|
|
12
22
|
try {
|
|
13
23
|
const txBuffer = toUint8Array(fromBase64(context.txBase64));
|
|
24
|
+
const isCbor = hasCborSelfDescribeTag(txBuffer);
|
|
25
|
+
const tx = isCbor ? decodeTx(txBuffer) : decodeTx$1(txBuffer);
|
|
14
26
|
Object.defineProperty(context, "tx", {
|
|
15
|
-
value:
|
|
27
|
+
value: tx,
|
|
28
|
+
enumerable: true
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(context, "txEncoding", {
|
|
31
|
+
value: isCbor ? "cbor" : "protobuf",
|
|
16
32
|
enumerable: true
|
|
17
33
|
});
|
|
18
34
|
Object.defineProperty(context, "txSize", {
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { encodeTxByEncoding } from "../helpers/encode-tx-by-context.mjs";
|
|
2
|
+
import { unwrapOpaqueAnyData } from "../helpers/unwrap-opaque-any.mjs";
|
|
1
3
|
import { CustomError } from "@ocap/util/lib/error";
|
|
2
4
|
import get from "lodash/get.js";
|
|
3
|
-
import {
|
|
4
|
-
import { getListField } from "@ocap/util/lib/get-list-field";
|
|
5
|
+
import { decodeAny } from "@ocap/message";
|
|
6
|
+
import { getListField, setListField } from "@ocap/util/lib/get-list-field";
|
|
5
7
|
import { toTypeInfo } from "@arcblock/did";
|
|
6
8
|
import cloneDeep from "lodash/cloneDeep.js";
|
|
7
9
|
import { fromPublicKey } from "@ocap/wallet";
|
|
@@ -17,22 +19,17 @@ function CreateVerifyMultiSigV2Pipe({ signersKey }) {
|
|
|
17
19
|
if (signatures.length !== signers.length) return next(new CustomError("INVALID_SIGNATURE", `Expect ${signers.length} signatures but found ${signatures.length}`));
|
|
18
20
|
for (const signer of signers) if (!signatures.find((x) => [x.delegator, x.signer].includes(signer))) return next(new CustomError("INVALID_SIGNATURE", `Signature for ${signer} not found in tx.signatures`));
|
|
19
21
|
signatures.forEach((sig) => {
|
|
20
|
-
|
|
21
|
-
if (decoded?.type && ["json", "vc"].includes(decoded.type)) try {
|
|
22
|
-
decoded.value = JSON.parse(Buffer.from(decoded.value, "base64").toString());
|
|
23
|
-
} catch (_e) {}
|
|
24
|
-
sig.data = decoded;
|
|
22
|
+
sig.data = unwrapOpaqueAnyData(sig.data ? decodeAny(sig.data) : void 0);
|
|
25
23
|
});
|
|
26
24
|
tx.signature = void 0;
|
|
27
|
-
tx
|
|
25
|
+
setListField(tx, "signatures", signatures.map((x) => omit(x, "signature")));
|
|
28
26
|
for (let i = 0; i < signatures.length; i++) {
|
|
29
27
|
const { signer, pk, delegator, signature, extra = "" } = signatures[i];
|
|
30
28
|
const address = delegator || signer;
|
|
31
29
|
const wallet = fromPublicKey(pk, toTypeInfo(address));
|
|
32
|
-
const
|
|
33
|
-
if (!message) return next(new CustomError("INVALID_SIGNATURE", `Failed to create message for ${address}`));
|
|
30
|
+
const txBytes = encodeTxByEncoding(context.txEncoding, tx);
|
|
34
31
|
try {
|
|
35
|
-
if (await wallet.verify(
|
|
32
|
+
if (await wallet.verify(txBytes, signature, true, extra) === false) return next(new CustomError("INVALID_SIGNATURE", `Signature for ${address} is not valid`));
|
|
36
33
|
} catch (err) {
|
|
37
34
|
console.error(err);
|
|
38
35
|
return next(new CustomError("INVALID_SIGNATURE", `Signature for ${address} verify failed: ${err.message}`));
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { encodeTxByEncoding } from "../helpers/encode-tx-by-context.mjs";
|
|
2
|
+
import { unwrapOpaqueAnyData } from "../helpers/unwrap-opaque-any.mjs";
|
|
1
3
|
import { CustomError } from "@ocap/util/lib/error";
|
|
2
|
-
import {
|
|
3
|
-
import { getListField } from "@ocap/util/lib/get-list-field";
|
|
4
|
+
import { decodeAny } from "@ocap/message";
|
|
5
|
+
import { deleteListField, getListField, setListField } from "@ocap/util/lib/get-list-field";
|
|
4
6
|
import { toTypeInfo } from "@arcblock/did";
|
|
5
7
|
import cloneDeep from "lodash/cloneDeep.js";
|
|
6
8
|
import { fromPublicKey } from "@ocap/wallet";
|
|
@@ -12,24 +14,19 @@ function CreateVerifyMultiSigPipe(numSigs = 0) {
|
|
|
12
14
|
const signatures = getListField(tx, "signatures");
|
|
13
15
|
if (signatures.length !== numSigs) return next(new CustomError("INVALID_SIGNATURE", `Expect ${numSigs} multi signatures but found ${signatures.length}`));
|
|
14
16
|
if (numSigs === 0) return next();
|
|
15
|
-
|
|
16
|
-
delete tx.signaturesList;
|
|
17
|
+
deleteListField(tx, "signatures");
|
|
17
18
|
while (signatures.length > 0) {
|
|
18
19
|
const { signer, pk, delegator, signature, data } = signatures.shift();
|
|
19
20
|
const address = delegator || signer;
|
|
20
21
|
const wallet = fromPublicKey(pk, toTypeInfo(address));
|
|
21
|
-
|
|
22
|
-
if (decoded?.type && ["json", "vc"].includes(decoded.type)) try {
|
|
23
|
-
decoded.value = JSON.parse(Buffer.from(decoded.value, "base64").toString());
|
|
24
|
-
} catch (_e) {}
|
|
25
|
-
tx.signatures = [{
|
|
22
|
+
setListField(tx, "signatures", [{
|
|
26
23
|
signer,
|
|
27
24
|
pk,
|
|
28
25
|
delegator,
|
|
29
|
-
data:
|
|
30
|
-
}].concat(signatures);
|
|
31
|
-
const
|
|
32
|
-
if (
|
|
26
|
+
data: unwrapOpaqueAnyData(data ? decodeAny(data) : void 0)
|
|
27
|
+
}].concat(signatures));
|
|
28
|
+
const txBytes = encodeTxByEncoding(context.txEncoding, tx);
|
|
29
|
+
if (await wallet.verify(txBytes, signature) === false) return next(new CustomError("INVALID_SIGNATURE", `Multi signature for ${address} is not valid`));
|
|
33
30
|
}
|
|
34
31
|
next();
|
|
35
32
|
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { encodeTxByEncoding } from "../helpers/encode-tx-by-context.mjs";
|
|
1
2
|
import { CustomError } from "@ocap/util/lib/error";
|
|
2
3
|
import get from "lodash/get.js";
|
|
3
|
-
import { createMessage } from "@ocap/message";
|
|
4
4
|
import { types } from "@ocap/mcrypto";
|
|
5
|
+
import { deleteListField } from "@ocap/util/lib/get-list-field";
|
|
5
6
|
import { isFromPublicKey, toTypeInfo } from "@arcblock/did";
|
|
6
7
|
import cloneDeep from "lodash/cloneDeep.js";
|
|
7
8
|
import { fromPublicKey } from "@ocap/wallet";
|
|
@@ -13,20 +14,16 @@ async function VerifySignature(context, next) {
|
|
|
13
14
|
tx.signature = void 0;
|
|
14
15
|
const multiSignV2Txs = get(context, "config.transaction.multiSignV2Txs", []);
|
|
15
16
|
const txType = context.txType;
|
|
16
|
-
if (!txType || multiSignV2Txs.includes(txType) === false)
|
|
17
|
-
delete tx.signatures;
|
|
18
|
-
delete tx.signaturesList;
|
|
19
|
-
}
|
|
17
|
+
if (!txType || multiSignV2Txs.includes(txType) === false) deleteListField(tx, "signatures");
|
|
20
18
|
const { pk, delegator, from } = tx;
|
|
21
19
|
const signer = delegator || from;
|
|
22
20
|
if (isFromPublicKey(signer, pk) === false) return next(new CustomError("INVALID_SIGNATURE", "signer and pk does not match"));
|
|
23
|
-
const
|
|
24
|
-
if (!message) return next(new CustomError("INVALID_SIGNATURE", "Failed to create transaction message"));
|
|
21
|
+
const txBytes = encodeTxByEncoding(context.txEncoding, tx);
|
|
25
22
|
const type = toTypeInfo(signer);
|
|
26
23
|
const wallet = fromPublicKey(pk, type);
|
|
27
24
|
const extra = type.role === types.RoleType.ROLE_PASSKEY ? get(context, "extra.txExtra") : "";
|
|
28
25
|
try {
|
|
29
|
-
if (!signature || await wallet.verify(
|
|
26
|
+
if (!signature || await wallet.verify(txBytes, signature, true, extra || "") === false) return next(new CustomError("INVALID_SIGNATURE", "tx.signature is invalid"));
|
|
30
27
|
} catch (err) {
|
|
31
28
|
console.error("tx.signature verify failed", err);
|
|
32
29
|
return next(new CustomError("INVALID_SIGNATURE", "tx.signature verify failed"));
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { CustomError } from "@ocap/util/lib/error";
|
|
2
2
|
import get from "lodash/get.js";
|
|
3
|
+
import { toTypeUrl } from "@ocap/message";
|
|
3
4
|
|
|
4
5
|
//#region src/pipes/verify-tx-size.ts
|
|
5
6
|
function VerifyTxSize(context, next) {
|
|
6
7
|
const { txSize, txType, tx, config } = context;
|
|
7
8
|
const defaultSizeLimit = get(config, "transaction.maxTxSize.default");
|
|
8
|
-
const
|
|
9
|
+
const rawItx = tx.itx;
|
|
10
|
+
const sizeLimit = get(config, `transaction.maxTxSize.${txType || rawItx?.typeUrl || (rawItx?.type ? toTypeUrl(rawItx.type) : void 0)}`, defaultSizeLimit);
|
|
9
11
|
if (txSize > sizeLimit) return next(new CustomError("INVALID_TX_SIZE", `Transaction size too large for ${txType}: expect ${sizeLimit}, got ${txSize}`));
|
|
10
12
|
next();
|
|
11
13
|
}
|
package/esm/pipes/verify-tx.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CustomError } from "@ocap/util/lib/error";
|
|
2
2
|
import get from "lodash/get.js";
|
|
3
|
+
import { toTypeUrl } from "@ocap/message";
|
|
3
4
|
import { getListField } from "@ocap/util/lib/get-list-field";
|
|
4
5
|
import { isFromPublicKey } from "@arcblock/did";
|
|
5
6
|
import isEmpty from "lodash/isEmpty.js";
|
|
@@ -19,7 +20,9 @@ function VerifyTx(context, next) {
|
|
|
19
20
|
const n = Number(nonce);
|
|
20
21
|
if (Number.isNaN(n) || n < 0) return next(new CustomError("INVALID_NONCE", "tx.nonce should be a positive integer"));
|
|
21
22
|
const { supportedTxs, maxMultisig } = get(context, "config.transaction");
|
|
22
|
-
|
|
23
|
+
const rawItx = itx;
|
|
24
|
+
const itxTypeUrl = rawItx.typeUrl || (rawItx.type ? toTypeUrl(rawItx.type) : void 0);
|
|
25
|
+
if (!itxTypeUrl || supportedTxs.includes(itxTypeUrl) === false) return next(new CustomError("UNSUPPORTED_TX", `Transaction ${itxTypeUrl} is not supported`));
|
|
23
26
|
if (getListField(context, "tx.signatures").length > maxMultisig) return next(new CustomError("INVALID_TX", "Too many multisig signatures"));
|
|
24
27
|
if (isFromPublicKey(delegator || from, pk) === false) return next(new CustomError("INVALID_TX", "Sender or delegator address does not match pk"));
|
|
25
28
|
next();
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
let _ocap_message_cbor = require("@ocap/message/cbor");
|
|
3
|
+
let _ocap_message_protobuf = require("@ocap/message/protobuf");
|
|
4
|
+
|
|
5
|
+
//#region src/helpers/encode-tx-by-context.ts
|
|
6
|
+
/**
|
|
7
|
+
* Pick the encoder matching `context.txEncoding`. Centralizes the ternary
|
|
8
|
+
* that lived in three verify pipes so future encoding additions touch one
|
|
9
|
+
* place. Chain-side only — client bundles that want tree-shake keep their
|
|
10
|
+
* local selection.
|
|
11
|
+
*/
|
|
12
|
+
function encodeTxByEncoding(encoding, tx) {
|
|
13
|
+
return encoding === "cbor" ? (0, _ocap_message_cbor.encodeTx)(tx) : (0, _ocap_message_protobuf.encodeTx)(tx);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
//#endregion
|
|
17
|
+
exports.encodeTxByEncoding = encodeTxByEncoding;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/helpers/encode-tx-by-context.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Pick the encoder matching `context.txEncoding`. Centralizes the ternary
|
|
4
|
+
* that lived in three verify pipes so future encoding additions touch one
|
|
5
|
+
* place. Chain-side only — client bundles that want tree-shake keep their
|
|
6
|
+
* local selection.
|
|
7
|
+
*/
|
|
8
|
+
declare function encodeTxByEncoding(encoding: string | undefined, tx: Record<string, unknown>): Uint8Array;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { encodeTxByEncoding };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/helpers/unwrap-opaque-any.ts
|
|
3
|
+
/**
|
|
4
|
+
* Undo the duplicate base64+JSON serialization that `decodeAny` leaves on
|
|
5
|
+
* `json` / `vc` typed Any payloads. Mutates `decoded.value` in place when
|
|
6
|
+
* applicable and is a no-op otherwise (including on malformed JSON — we
|
|
7
|
+
* swallow the parse error to keep legacy behavior).
|
|
8
|
+
*
|
|
9
|
+
* HACK carried forward from pre-Phase-43 multisig verifiers; kept in one
|
|
10
|
+
* place so the two verify pipes share the exact same fallback.
|
|
11
|
+
*/
|
|
12
|
+
function unwrapOpaqueAnyData(decoded) {
|
|
13
|
+
if (decoded?.type && ["json", "vc"].includes(decoded.type)) try {
|
|
14
|
+
decoded.value = JSON.parse(Buffer.from(decoded.value, "base64").toString());
|
|
15
|
+
} catch (_e) {}
|
|
16
|
+
return decoded;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
//#endregion
|
|
20
|
+
exports.unwrapOpaqueAnyData = unwrapOpaqueAnyData;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/helpers/unwrap-opaque-any.d.ts
|
|
2
|
+
interface DecodedAny {
|
|
3
|
+
type?: string;
|
|
4
|
+
value?: unknown;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Undo the duplicate base64+JSON serialization that `decodeAny` leaves on
|
|
8
|
+
* `json` / `vc` typed Any payloads. Mutates `decoded.value` in place when
|
|
9
|
+
* applicable and is a no-op otherwise (including on malformed JSON — we
|
|
10
|
+
* swallow the parse error to keep legacy behavior).
|
|
11
|
+
*
|
|
12
|
+
* HACK carried forward from pre-Phase-43 multisig verifiers; kept in one
|
|
13
|
+
* place so the two verify pipes share the exact same fallback.
|
|
14
|
+
*/
|
|
15
|
+
declare function unwrapOpaqueAnyData(decoded: DecodedAny | undefined): DecodedAny | undefined;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { unwrapOpaqueAnyData };
|
package/lib/pipes/decode-itx.cjs
CHANGED
|
@@ -4,16 +4,63 @@ let _ocap_util_lib_error = require("@ocap/util/lib/error");
|
|
|
4
4
|
let _ocap_message = require("@ocap/message");
|
|
5
5
|
|
|
6
6
|
//#region src/pipes/decode-itx.ts
|
|
7
|
+
/**
|
|
8
|
+
* Normalize `tx.itx` to a `{ typeUrl, value }` pair across the three shapes
|
|
9
|
+
* that reach this pipe:
|
|
10
|
+
*
|
|
11
|
+
* protobuf wire → jspb Any.toObject() → `{ typeUrl, value: <base64-bytes> }`
|
|
12
|
+
* cbor wire → canonical-cbor flat Any → `{ typeUrl, ...inner }`
|
|
13
|
+
* client raw → pre-encoding object → `{ type, value: { ...inner } }`
|
|
14
|
+
*
|
|
15
|
+
* Downstream protocol schemas and pipes expect the jspb-shaped inner object
|
|
16
|
+
* (repeated fields carry the `xxxList` alias, bytes fields are base64 strings,
|
|
17
|
+
* BigUint wrappers are `{ value: Uint8Array }`). We round-trip the cbor /
|
|
18
|
+
* client-raw cases through `createMessage().toObject()` so downstream code
|
|
19
|
+
* sees a single, stable shape regardless of wire format.
|
|
20
|
+
*/
|
|
21
|
+
function toJspbObject(typeUrl, inner) {
|
|
22
|
+
const msg = (0, _ocap_message.createMessage)((0, _ocap_message.fromTypeUrl)(typeUrl), inner);
|
|
23
|
+
return msg?.toObject ? msg.toObject() : inner;
|
|
24
|
+
}
|
|
25
|
+
function normalizeItx(raw) {
|
|
26
|
+
if (!raw || typeof raw !== "object") return null;
|
|
27
|
+
if (raw.typeUrl) {
|
|
28
|
+
if (typeof raw.value === "string") {
|
|
29
|
+
const decoded = (0, _ocap_message.decodeAny)(raw);
|
|
30
|
+
return {
|
|
31
|
+
typeUrl: raw.typeUrl,
|
|
32
|
+
value: decoded.value
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
const inner = {};
|
|
36
|
+
for (const [key, val] of Object.entries(raw)) {
|
|
37
|
+
if (key === "typeUrl" || key === "type_url") continue;
|
|
38
|
+
inner[key] = val;
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
typeUrl: raw.typeUrl,
|
|
42
|
+
value: toJspbObject(raw.typeUrl, inner)
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
if (raw.type) {
|
|
46
|
+
const typeUrl = (0, _ocap_message.toTypeUrl)(raw.type);
|
|
47
|
+
return {
|
|
48
|
+
typeUrl,
|
|
49
|
+
value: toJspbObject(typeUrl, raw.value || {})
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
7
54
|
function DecodeItx(context, next) {
|
|
8
55
|
try {
|
|
9
|
-
const
|
|
10
|
-
|
|
56
|
+
const normalized = normalizeItx(context.tx.itx);
|
|
57
|
+
if (!normalized) return next(new _ocap_util_lib_error.CustomError("INVALID_TX", "Failed to decode itx"));
|
|
11
58
|
Object.defineProperty(context, "itx", {
|
|
12
|
-
value:
|
|
59
|
+
value: normalized.value,
|
|
13
60
|
enumerable: true
|
|
14
61
|
});
|
|
15
62
|
Object.defineProperty(context, "txType", {
|
|
16
|
-
value:
|
|
63
|
+
value: normalized.typeUrl,
|
|
17
64
|
enumerable: true
|
|
18
65
|
});
|
|
19
66
|
context.logger?.info("Tx decoded", {
|
|
@@ -21,7 +68,7 @@ function DecodeItx(context, next) {
|
|
|
21
68
|
txHash: context.txHash,
|
|
22
69
|
txTime: context.txTime,
|
|
23
70
|
txSize: context.txSize,
|
|
24
|
-
txType,
|
|
71
|
+
txType: normalized.typeUrl,
|
|
25
72
|
request: context.extra?.request
|
|
26
73
|
});
|
|
27
74
|
} catch (_err) {
|
package/lib/pipes/decode-tx.cjs
CHANGED
|
@@ -3,19 +3,35 @@ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
|
3
3
|
const require_package = require('../package.cjs');
|
|
4
4
|
let _ocap_util = require("@ocap/util");
|
|
5
5
|
let _ocap_util_lib_error = require("@ocap/util/lib/error");
|
|
6
|
-
let _ocap_message = require("@ocap/message");
|
|
7
6
|
let _ocap_mcrypto = require("@ocap/mcrypto");
|
|
7
|
+
let _ocap_message_cbor = require("@ocap/message/cbor");
|
|
8
|
+
let _ocap_message_protobuf = require("@ocap/message/protobuf");
|
|
8
9
|
let debug = require("debug");
|
|
9
10
|
debug = require_rolldown_runtime.__toESM(debug);
|
|
10
11
|
|
|
11
12
|
//#region src/pipes/decode-tx.ts
|
|
12
13
|
const debug$1 = (0, debug.default)(`${require_package.name}:pipe:decode-tx`);
|
|
13
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Detect the CBOR self-describe tag 55799 that our canonical encoder always
|
|
16
|
+
* prepends to a Transaction. The first three bytes are unambiguously distinct
|
|
17
|
+
* from any protobuf encoding of Transaction because `D9` = `(27 << 3) | 1`,
|
|
18
|
+
* and `Transaction` has no top-level field number ≥ 27 (enforced by
|
|
19
|
+
* `scripts/assert-proto-field-bound.ts`).
|
|
20
|
+
*/
|
|
21
|
+
function hasCborSelfDescribeTag(buf) {
|
|
22
|
+
return buf.length >= _ocap_message_cbor.CANONICAL_SELF_DESCRIBE_PREFIX.length && buf[0] === _ocap_message_cbor.CANONICAL_SELF_DESCRIBE_PREFIX[0] && buf[1] === _ocap_message_cbor.CANONICAL_SELF_DESCRIBE_PREFIX[1] && buf[2] === _ocap_message_cbor.CANONICAL_SELF_DESCRIBE_PREFIX[2];
|
|
23
|
+
}
|
|
14
24
|
function DecodeTx(context, next) {
|
|
15
25
|
try {
|
|
16
26
|
const txBuffer = (0, _ocap_util.toUint8Array)((0, _ocap_util.fromBase64)(context.txBase64));
|
|
27
|
+
const isCbor = hasCborSelfDescribeTag(txBuffer);
|
|
28
|
+
const tx = isCbor ? (0, _ocap_message_cbor.decodeTx)(txBuffer) : (0, _ocap_message_protobuf.decodeTx)(txBuffer);
|
|
17
29
|
Object.defineProperty(context, "tx", {
|
|
18
|
-
value:
|
|
30
|
+
value: tx,
|
|
31
|
+
enumerable: true
|
|
32
|
+
});
|
|
33
|
+
Object.defineProperty(context, "txEncoding", {
|
|
34
|
+
value: isCbor ? "cbor" : "protobuf",
|
|
19
35
|
enumerable: true
|
|
20
36
|
});
|
|
21
37
|
Object.defineProperty(context, "txSize", {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2
2
|
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
3
|
+
const require_helpers_encode_tx_by_context = require('../helpers/encode-tx-by-context.cjs');
|
|
4
|
+
const require_helpers_unwrap_opaque_any = require('../helpers/unwrap-opaque-any.cjs');
|
|
3
5
|
let _ocap_util_lib_error = require("@ocap/util/lib/error");
|
|
4
6
|
let lodash_get = require("lodash/get");
|
|
5
7
|
lodash_get = require_rolldown_runtime.__toESM(lodash_get);
|
|
@@ -22,22 +24,17 @@ function CreateVerifyMultiSigV2Pipe({ signersKey }) {
|
|
|
22
24
|
if (signatures.length !== signers.length) return next(new _ocap_util_lib_error.CustomError("INVALID_SIGNATURE", `Expect ${signers.length} signatures but found ${signatures.length}`));
|
|
23
25
|
for (const signer of signers) if (!signatures.find((x) => [x.delegator, x.signer].includes(signer))) return next(new _ocap_util_lib_error.CustomError("INVALID_SIGNATURE", `Signature for ${signer} not found in tx.signatures`));
|
|
24
26
|
signatures.forEach((sig) => {
|
|
25
|
-
|
|
26
|
-
if (decoded?.type && ["json", "vc"].includes(decoded.type)) try {
|
|
27
|
-
decoded.value = JSON.parse(Buffer.from(decoded.value, "base64").toString());
|
|
28
|
-
} catch (_e) {}
|
|
29
|
-
sig.data = decoded;
|
|
27
|
+
sig.data = require_helpers_unwrap_opaque_any.unwrapOpaqueAnyData(sig.data ? (0, _ocap_message.decodeAny)(sig.data) : void 0);
|
|
30
28
|
});
|
|
31
29
|
tx.signature = void 0;
|
|
32
|
-
tx
|
|
30
|
+
(0, _ocap_util_lib_get_list_field.setListField)(tx, "signatures", signatures.map((x) => (0, lodash_omit.default)(x, "signature")));
|
|
33
31
|
for (let i = 0; i < signatures.length; i++) {
|
|
34
32
|
const { signer, pk, delegator, signature, extra = "" } = signatures[i];
|
|
35
33
|
const address = delegator || signer;
|
|
36
34
|
const wallet = (0, _ocap_wallet.fromPublicKey)(pk, (0, _arcblock_did.toTypeInfo)(address));
|
|
37
|
-
const
|
|
38
|
-
if (!message) return next(new _ocap_util_lib_error.CustomError("INVALID_SIGNATURE", `Failed to create message for ${address}`));
|
|
35
|
+
const txBytes = require_helpers_encode_tx_by_context.encodeTxByEncoding(context.txEncoding, tx);
|
|
39
36
|
try {
|
|
40
|
-
if (await wallet.verify(
|
|
37
|
+
if (await wallet.verify(txBytes, signature, true, extra) === false) return next(new _ocap_util_lib_error.CustomError("INVALID_SIGNATURE", `Signature for ${address} is not valid`));
|
|
41
38
|
} catch (err) {
|
|
42
39
|
console.error(err);
|
|
43
40
|
return next(new _ocap_util_lib_error.CustomError("INVALID_SIGNATURE", `Signature for ${address} verify failed: ${err.message}`));
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2
2
|
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
3
|
+
const require_helpers_encode_tx_by_context = require('../helpers/encode-tx-by-context.cjs');
|
|
4
|
+
const require_helpers_unwrap_opaque_any = require('../helpers/unwrap-opaque-any.cjs');
|
|
3
5
|
let _ocap_util_lib_error = require("@ocap/util/lib/error");
|
|
4
6
|
let _ocap_message = require("@ocap/message");
|
|
5
7
|
let _ocap_util_lib_get_list_field = require("@ocap/util/lib/get-list-field");
|
|
@@ -15,24 +17,19 @@ function CreateVerifyMultiSigPipe(numSigs = 0) {
|
|
|
15
17
|
const signatures = (0, _ocap_util_lib_get_list_field.getListField)(tx, "signatures");
|
|
16
18
|
if (signatures.length !== numSigs) return next(new _ocap_util_lib_error.CustomError("INVALID_SIGNATURE", `Expect ${numSigs} multi signatures but found ${signatures.length}`));
|
|
17
19
|
if (numSigs === 0) return next();
|
|
18
|
-
|
|
19
|
-
delete tx.signaturesList;
|
|
20
|
+
(0, _ocap_util_lib_get_list_field.deleteListField)(tx, "signatures");
|
|
20
21
|
while (signatures.length > 0) {
|
|
21
22
|
const { signer, pk, delegator, signature, data } = signatures.shift();
|
|
22
23
|
const address = delegator || signer;
|
|
23
24
|
const wallet = (0, _ocap_wallet.fromPublicKey)(pk, (0, _arcblock_did.toTypeInfo)(address));
|
|
24
|
-
|
|
25
|
-
if (decoded?.type && ["json", "vc"].includes(decoded.type)) try {
|
|
26
|
-
decoded.value = JSON.parse(Buffer.from(decoded.value, "base64").toString());
|
|
27
|
-
} catch (_e) {}
|
|
28
|
-
tx.signatures = [{
|
|
25
|
+
(0, _ocap_util_lib_get_list_field.setListField)(tx, "signatures", [{
|
|
29
26
|
signer,
|
|
30
27
|
pk,
|
|
31
28
|
delegator,
|
|
32
|
-
data:
|
|
33
|
-
}].concat(signatures);
|
|
34
|
-
const
|
|
35
|
-
if (
|
|
29
|
+
data: require_helpers_unwrap_opaque_any.unwrapOpaqueAnyData(data ? (0, _ocap_message.decodeAny)(data) : void 0)
|
|
30
|
+
}].concat(signatures));
|
|
31
|
+
const txBytes = require_helpers_encode_tx_by_context.encodeTxByEncoding(context.txEncoding, tx);
|
|
32
|
+
if (await wallet.verify(txBytes, signature) === false) return next(new _ocap_util_lib_error.CustomError("INVALID_SIGNATURE", `Multi signature for ${address} is not valid`));
|
|
36
33
|
}
|
|
37
34
|
next();
|
|
38
35
|
};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2
2
|
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
3
|
+
const require_helpers_encode_tx_by_context = require('../helpers/encode-tx-by-context.cjs');
|
|
3
4
|
let _ocap_util_lib_error = require("@ocap/util/lib/error");
|
|
4
5
|
let lodash_get = require("lodash/get");
|
|
5
6
|
lodash_get = require_rolldown_runtime.__toESM(lodash_get);
|
|
6
|
-
let _ocap_message = require("@ocap/message");
|
|
7
7
|
let _ocap_mcrypto = require("@ocap/mcrypto");
|
|
8
|
+
let _ocap_util_lib_get_list_field = require("@ocap/util/lib/get-list-field");
|
|
8
9
|
let _arcblock_did = require("@arcblock/did");
|
|
9
10
|
let lodash_cloneDeep = require("lodash/cloneDeep");
|
|
10
11
|
lodash_cloneDeep = require_rolldown_runtime.__toESM(lodash_cloneDeep);
|
|
@@ -17,20 +18,16 @@ async function VerifySignature(context, next) {
|
|
|
17
18
|
tx.signature = void 0;
|
|
18
19
|
const multiSignV2Txs = (0, lodash_get.default)(context, "config.transaction.multiSignV2Txs", []);
|
|
19
20
|
const txType = context.txType;
|
|
20
|
-
if (!txType || multiSignV2Txs.includes(txType) === false)
|
|
21
|
-
delete tx.signatures;
|
|
22
|
-
delete tx.signaturesList;
|
|
23
|
-
}
|
|
21
|
+
if (!txType || multiSignV2Txs.includes(txType) === false) (0, _ocap_util_lib_get_list_field.deleteListField)(tx, "signatures");
|
|
24
22
|
const { pk, delegator, from } = tx;
|
|
25
23
|
const signer = delegator || from;
|
|
26
24
|
if ((0, _arcblock_did.isFromPublicKey)(signer, pk) === false) return next(new _ocap_util_lib_error.CustomError("INVALID_SIGNATURE", "signer and pk does not match"));
|
|
27
|
-
const
|
|
28
|
-
if (!message) return next(new _ocap_util_lib_error.CustomError("INVALID_SIGNATURE", "Failed to create transaction message"));
|
|
25
|
+
const txBytes = require_helpers_encode_tx_by_context.encodeTxByEncoding(context.txEncoding, tx);
|
|
29
26
|
const type = (0, _arcblock_did.toTypeInfo)(signer);
|
|
30
27
|
const wallet = (0, _ocap_wallet.fromPublicKey)(pk, type);
|
|
31
28
|
const extra = type.role === _ocap_mcrypto.types.RoleType.ROLE_PASSKEY ? (0, lodash_get.default)(context, "extra.txExtra") : "";
|
|
32
29
|
try {
|
|
33
|
-
if (!signature || await wallet.verify(
|
|
30
|
+
if (!signature || await wallet.verify(txBytes, signature, true, extra || "") === false) return next(new _ocap_util_lib_error.CustomError("INVALID_SIGNATURE", "tx.signature is invalid"));
|
|
34
31
|
} catch (err) {
|
|
35
32
|
console.error("tx.signature verify failed", err);
|
|
36
33
|
return next(new _ocap_util_lib_error.CustomError("INVALID_SIGNATURE", "tx.signature verify failed"));
|
|
@@ -3,12 +3,14 @@ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
|
3
3
|
let _ocap_util_lib_error = require("@ocap/util/lib/error");
|
|
4
4
|
let lodash_get = require("lodash/get");
|
|
5
5
|
lodash_get = require_rolldown_runtime.__toESM(lodash_get);
|
|
6
|
+
let _ocap_message = require("@ocap/message");
|
|
6
7
|
|
|
7
8
|
//#region src/pipes/verify-tx-size.ts
|
|
8
9
|
function VerifyTxSize(context, next) {
|
|
9
10
|
const { txSize, txType, tx, config } = context;
|
|
10
11
|
const defaultSizeLimit = (0, lodash_get.default)(config, "transaction.maxTxSize.default");
|
|
11
|
-
const
|
|
12
|
+
const rawItx = tx.itx;
|
|
13
|
+
const sizeLimit = (0, lodash_get.default)(config, `transaction.maxTxSize.${txType || rawItx?.typeUrl || (rawItx?.type ? (0, _ocap_message.toTypeUrl)(rawItx.type) : void 0)}`, defaultSizeLimit);
|
|
12
14
|
if (txSize > sizeLimit) return next(new _ocap_util_lib_error.CustomError("INVALID_TX_SIZE", `Transaction size too large for ${txType}: expect ${sizeLimit}, got ${txSize}`));
|
|
13
15
|
next();
|
|
14
16
|
}
|
package/lib/pipes/verify-tx.cjs
CHANGED
|
@@ -3,6 +3,7 @@ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
|
3
3
|
let _ocap_util_lib_error = require("@ocap/util/lib/error");
|
|
4
4
|
let lodash_get = require("lodash/get");
|
|
5
5
|
lodash_get = require_rolldown_runtime.__toESM(lodash_get);
|
|
6
|
+
let _ocap_message = require("@ocap/message");
|
|
6
7
|
let _ocap_util_lib_get_list_field = require("@ocap/util/lib/get-list-field");
|
|
7
8
|
let _arcblock_did = require("@arcblock/did");
|
|
8
9
|
let lodash_isEmpty = require("lodash/isEmpty");
|
|
@@ -23,7 +24,9 @@ function VerifyTx(context, next) {
|
|
|
23
24
|
const n = Number(nonce);
|
|
24
25
|
if (Number.isNaN(n) || n < 0) return next(new _ocap_util_lib_error.CustomError("INVALID_NONCE", "tx.nonce should be a positive integer"));
|
|
25
26
|
const { supportedTxs, maxMultisig } = (0, lodash_get.default)(context, "config.transaction");
|
|
26
|
-
|
|
27
|
+
const rawItx = itx;
|
|
28
|
+
const itxTypeUrl = rawItx.typeUrl || (rawItx.type ? (0, _ocap_message.toTypeUrl)(rawItx.type) : void 0);
|
|
29
|
+
if (!itxTypeUrl || supportedTxs.includes(itxTypeUrl) === false) return next(new _ocap_util_lib_error.CustomError("UNSUPPORTED_TX", `Transaction ${itxTypeUrl} is not supported`));
|
|
27
30
|
if ((0, _ocap_util_lib_get_list_field.getListField)(context, "tx.signatures").length > maxMultisig) return next(new _ocap_util_lib_error.CustomError("INVALID_TX", "Too many multisig signatures"));
|
|
28
31
|
if ((0, _arcblock_did.isFromPublicKey)(delegator || from, pk) === false) return next(new _ocap_util_lib_error.CustomError("INVALID_TX", "Sender or delegator address does not match pk"));
|
|
29
32
|
next();
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.30.
|
|
6
|
+
"version": "1.30.4",
|
|
7
7
|
"description": "Pipeline runner and common pipelines to process transactions",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"main": "./lib/index.cjs",
|
|
@@ -49,15 +49,15 @@
|
|
|
49
49
|
"elliptic": "6.5.3"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@arcblock/did": "1.30.
|
|
53
|
-
"@arcblock/did-util": "1.30.
|
|
54
|
-
"@ocap/client": "1.30.
|
|
55
|
-
"@ocap/mcrypto": "1.30.
|
|
56
|
-
"@ocap/message": "1.30.
|
|
57
|
-
"@ocap/state": "1.30.
|
|
58
|
-
"@ocap/types": "1.30.
|
|
59
|
-
"@ocap/util": "1.30.
|
|
60
|
-
"@ocap/wallet": "1.30.
|
|
52
|
+
"@arcblock/did": "1.30.4",
|
|
53
|
+
"@arcblock/did-util": "1.30.4",
|
|
54
|
+
"@ocap/client": "1.30.4",
|
|
55
|
+
"@ocap/mcrypto": "1.30.4",
|
|
56
|
+
"@ocap/message": "1.30.4",
|
|
57
|
+
"@ocap/state": "1.30.4",
|
|
58
|
+
"@ocap/types": "1.30.4",
|
|
59
|
+
"@ocap/util": "1.30.4",
|
|
60
|
+
"@ocap/wallet": "1.30.4",
|
|
61
61
|
"debug": "^4.4.3",
|
|
62
62
|
"lodash": "^4.17.23"
|
|
63
63
|
}
|