From e8620ccea9615821593d5c2dfccb8d8b11878928 Mon Sep 17 00:00:00 2001 From: Csongor Kiss Date: Fri, 1 Jul 2022 00:02:16 +0100 Subject: [PATCH] clients/js: Dump payload in case of parse failure --- clients/js/main.ts | 4 +- clients/js/parse_tests/base64-2.expected | 22 ++++ clients/js/parse_tests/base64-2.test | 1 + clients/js/vaa.ts | 142 +++++++++++++---------- 4 files changed, 103 insertions(+), 66 deletions(-) create mode 100644 clients/js/parse_tests/base64-2.expected create mode 100644 clients/js/parse_tests/base64-2.test diff --git a/clients/js/main.ts b/clients/js/main.ts index 4b68ab817..fd7677d36 100644 --- a/clients/js/main.ts +++ b/clients/js/main.ts @@ -452,9 +452,7 @@ yargs(hideBin(process.argv)) const buf = Buffer.from(vaa_hex, "hex"); const parsed_vaa = vaa.parse(buf); - if (!vaa.hasPayload(parsed_vaa)) { - throw Error("Couldn't parse VAA payload"); - } + vaa.assertKnownPayload(parsed_vaa); console.log(parsed_vaa.payload); diff --git a/clients/js/parse_tests/base64-2.expected b/clients/js/parse_tests/base64-2.expected new file mode 100644 index 000000000..9c8a7c558 --- /dev/null +++ b/clients/js/parse_tests/base64-2.expected @@ -0,0 +1,22 @@ +{ + version: 1, + guardianSetIndex: 0, + signatures: [ + { + guardianSetIndex: 0, + signature: 'e29d3ad180b153d68c3f445d75eaa62fcc99690945baaf4ad0463e9ce44f27f75da3d49f79722920aac81ba2be80f688895f174942fedc403bc4e5ce3555b77b00' + } + ], + timestamp: 1656354705, + nonce: 0, + emitterChain: 2, + emitterAddress: '0x000000000000000000000000f19a2a01b70519f67adb309a994ec8c69a967e8b', + sequence: 0n, + consistencyLevel: 1, + payload: { + type: 'Other', + hex: '46726f6d3a2065766d305c6e4d73673a2048656c6c6f20576f726c6421', + ascii: 'From: evm0\\nMsg: Hello World!' + }, + digest: '0x8b7781f662ff1eed4827b770c0e735288948f0b56611f8cd73bf65e6b2a7a8ad' +} diff --git a/clients/js/parse_tests/base64-2.test b/clients/js/parse_tests/base64-2.test new file mode 100644 index 000000000..47f286d39 --- /dev/null +++ b/clients/js/parse_tests/base64-2.test @@ -0,0 +1 @@ +AQAAAAABAOKdOtGAsVPWjD9EXXXqpi/MmWkJRbqvStBGPpzkTyf3XaPUn3lyKSCqyBuivoD2iIlfF0lC/txAO8TlzjVVt3sAYrn3kQAAAAAAAgAAAAAAAAAAAAAAAPGaKgG3BRn2etswmplOyMaaln6LAAAAAAAAAAABRnJvbTogZXZtMFxuTXNnOiBIZWxsbyBXb3JsZCE= diff --git a/clients/js/vaa.ts b/clients/js/vaa.ts index 5b523296c..39f4b4020 100644 --- a/clients/js/vaa.ts +++ b/clients/js/vaa.ts @@ -52,6 +52,12 @@ class P { } } +export interface Other { + type: "Other", + hex: string, + ascii?: string +} + // All the different types of payloads export type Payload = GuardianSetUpgrade @@ -70,7 +76,7 @@ export type ContractUpgrade = | PortalContractUpgrade<"TokenBridge"> | PortalContractUpgrade<"NFTBridge"> -export function parse(buffer: Buffer): VAA { +export function parse(buffer: Buffer): VAA { const vaa = parseEnvelope(buffer) const parser = guardianSetUpgradeParser .or(coreContractUpgradeParser) @@ -82,15 +88,21 @@ export function parse(buffer: Buffer): VAA { .or(tokenBridgeTransferWithPayloadParser()) .or(tokenBridgeAttestMetaParser()) .or(nftBridgeTransferParser()) - const payload = parser.parse(vaa.payload) - delete payload['tokenURILength'] + let payload : Payload | Other | null = parser.parse(vaa.payload) + if (payload === null) { + payload = {type: "Other", hex: Buffer.from(vaa.payload).toString("hex"), ascii: Buffer.from(vaa.payload).toString('utf8')} + } else { + delete payload['tokenURILength'] + } var myVAA = { ...vaa, payload } return myVAA } -export function hasPayload(vaa: VAA): vaa is VAA { - return vaa.payload !== null +export function assertKnownPayload(vaa: VAA): asserts vaa is VAA { + if (vaa.payload.type === "Other") { + throw Error(`Couldn't parse VAA payload: ${vaa.payload.hex}`); + } } // Parse the VAA envelope without looking into the payload. @@ -161,68 +173,72 @@ export function serialiseVAA(vaa: VAA) { return body.join("") } -export function vaaDigest(vaa: VAA) { +export function vaaDigest(vaa: VAA) { return solidityKeccak256(["bytes"], [solidityKeccak256(["bytes"], ["0x" + vaaBody(vaa)])]) } -function vaaBody(vaa: VAA) { - let payload = vaa.payload +function vaaBody(vaa: VAA) { let payload_str: string - switch (payload.module) { - case "Core": - switch (payload.type) { - case "GuardianSetUpgrade": - payload_str = serialiseGuardianSetUpgrade(payload) - break - case "ContractUpgrade": - payload_str = serialiseCoreContractUpgrade(payload) - break - default: - impossible(payload) - break - } - break - case "NFTBridge": - switch (payload.type) { - case "ContractUpgrade": - payload_str = serialisePortalContractUpgrade(payload) - break - case "RegisterChain": - payload_str = serialisePortalRegisterChain(payload) - break - case "Transfer": - payload_str = serialiseNFTBridgeTransfer(payload) - break - default: - impossible(payload) - break - } - break - case "TokenBridge": - switch (payload.type) { - case "ContractUpgrade": - payload_str = serialisePortalContractUpgrade(payload) - break - case "RegisterChain": - payload_str = serialisePortalRegisterChain(payload) - break - case "Transfer": - payload_str = serialiseTokenBridgeTransfer(payload) - break - case "TransferWithPayload": - payload_str = serialiseTokenBridgeTransferWithPayload(payload) - break - case "AttestMeta": - payload_str = serialiseTokenBridgeAttestMeta(payload) - break - default: - impossible(payload) - break - } - break - default: - impossible(payload) - break + if (vaa.payload.type === "Other") { + payload_str = vaa.payload.hex + } else { + let payload = vaa.payload; + switch (payload.module) { + case "Core": + switch (payload.type) { + case "GuardianSetUpgrade": + payload_str = serialiseGuardianSetUpgrade(payload) + break + case "ContractUpgrade": + payload_str = serialiseCoreContractUpgrade(payload) + break + default: + impossible(payload) + break + } + break + case "NFTBridge": + switch (payload.type) { + case "ContractUpgrade": + payload_str = serialisePortalContractUpgrade(payload) + break + case "RegisterChain": + payload_str = serialisePortalRegisterChain(payload) + break + case "Transfer": + payload_str = serialiseNFTBridgeTransfer(payload) + break + default: + impossible(payload) + break + } + break + case "TokenBridge": + switch (payload.type) { + case "ContractUpgrade": + payload_str = serialisePortalContractUpgrade(payload) + break + case "RegisterChain": + payload_str = serialisePortalRegisterChain(payload) + break + case "Transfer": + payload_str = serialiseTokenBridgeTransfer(payload) + break + case "TransferWithPayload": + payload_str = serialiseTokenBridgeTransferWithPayload(payload) + break + case "AttestMeta": + payload_str = serialiseTokenBridgeAttestMeta(payload) + break + default: + impossible(payload) + break + } + break + default: + impossible(payload) + break + } } const body = [ encode("uint32", vaa.timestamp),