Files
trezor-suite/packages/protobuf/tests/encode-decode.test.ts

547 lines
20 KiB
TypeScript

import * as ProtoBuf from 'protobufjs/light';
import { decode } from '../src/decode';
import { encode } from '../src/encode';
const HDNodeType = {
fields: {
depth: {
rule: 'required',
type: 'uint32',
id: 1,
},
fingerprint: {
rule: 'required',
type: 'uint32',
id: 2,
},
child_num: {
rule: 'required',
type: 'uint32',
id: 3,
},
chain_code: {
rule: 'required',
type: 'bytes',
id: 4,
},
private_key: {
type: 'bytes',
id: 5,
},
public_key: {
rule: 'required',
type: 'bytes',
id: 6,
},
},
};
const MultisigRedeemScriptType = {
fields: {
pubkeys: {
rule: 'repeated',
type: 'HDNodePathType',
id: 1,
},
signatures: {
rule: 'repeated',
type: 'bytes',
id: 2,
},
m: {
rule: 'required',
type: 'uint32',
id: 3,
},
nodes: {
rule: 'repeated',
type: 'HDNodeType',
id: 4,
},
address_n: {
rule: 'repeated',
type: 'uint32',
id: 5,
options: {
packed: false,
},
},
},
nested: {
HDNodePathType: {
fields: {
node: {
rule: 'required',
type: 'HDNodeType',
id: 1,
},
address_n: {
rule: 'repeated',
type: 'uint32',
id: 2,
options: {
packed: false,
},
},
},
},
},
};
const fixtures = [
{
name: 'Initialize',
message: {
Initialize: {
fields: {
session_id: {
type: 'bytes',
id: 0,
},
},
},
},
in: {},
encoded: '',
out: { session_id: null },
},
{
name: 'Address',
message: {
Address: {
fields: {
address: {
rule: 'required',
type: 'string',
id: 1,
},
},
},
},
in: { address: 'abcd' },
encoded: '0a0461626364',
out: { address: 'abcd' },
},
{
name: 'GetAddress',
message: {
GetAddress: {
fields: {
address_n: {
rule: 'repeated',
type: 'uint32',
id: 1,
options: {
packed: false,
},
},
coin_name: {
type: 'string',
id: 2,
options: {
default: 'Bitcoin',
},
},
show_display: {
type: 'bool',
id: 3,
},
multisig: {
type: 'MultisigRedeemScriptType',
id: 4,
},
ignore_xpub_magic: {
type: 'bool',
id: 6,
},
},
},
MultisigRedeemScriptType,
HDNodeType,
},
in: {
address_n: [1],
coin_name: 'btc',
show_display: null,
ignore_xpub_magic: null,
multisig: {
pubkeys: [
{
node: {
depth: 1,
fingerprint: 1,
child_num: 1,
chain_code:
'851fc9542342321af63ecbba7d3ece545f2a42bad01ba32cff5535b18e54b6d3106e10b6a4525993d185a1443d9a125186960e028eabfdd8d76cf70a3a7e3100',
private_key:
'851fc9542342321af63ecbba7d3ece545f2a42bad01ba32cff5535b18e54b6d3106e10b6a4525993d185a1443d9a125186960e028eabfdd8d76cf70a3a7e3100',
public_key:
'851fc9542342321af63ecbba7d3ece545f2a42bad01ba32cff5535b18e54b6d3106e10b6a4525993d185a1443d9a125186960e028eabfdd8d76cf70a3a7e3100',
},
address_n: [1],
},
],
signatures: [
'851fc9542342321af63ecbba7d3ece545f2a42bad01ba32cff5535b18e54b6d3106e10b6a4525993d185a1443d9a125186960e028eabfdd8d76cf70a3a7e3100',
],
m: 1,
nodes: [
{
depth: 1,
fingerprint: 1,
child_num: 1,
chain_code:
'851fc9542342321af63ecbba7d3ece545f2a42bad01ba32cff5535b18e54b6d3106e10b6a4525993d185a1443d9a125186960e028eabfdd8d76cf70a3a7e3100',
private_key:
'851fc9542342321af63ecbba7d3ece545f2a42bad01ba32cff5535b18e54b6d3106e10b6a4525993d185a1443d9a125186960e028eabfdd8d76cf70a3a7e3100',
public_key:
'851fc9542342321af63ecbba7d3ece545f2a42bad01ba32cff5535b18e54b6d3106e10b6a4525993d185a1443d9a125186960e028eabfdd8d76cf70a3a7e3100',
},
],
address_n: [1],
},
},
encoded:
'0801120362746322e9030ad1010acc010801100118012240851fc9542342321af63ecbba7d3ece545f2a42bad01ba32cff5535b18e54b6d3106e10b6a4525993d185a1443d9a125186960e028eabfdd8d76cf70a3a7e31002a40851fc9542342321af63ecbba7d3ece545f2a42bad01ba32cff5535b18e54b6d3106e10b6a4525993d185a1443d9a125186960e028eabfdd8d76cf70a3a7e31003240851fc9542342321af63ecbba7d3ece545f2a42bad01ba32cff5535b18e54b6d3106e10b6a4525993d185a1443d9a125186960e028eabfdd8d76cf70a3a7e310010011240851fc9542342321af63ecbba7d3ece545f2a42bad01ba32cff5535b18e54b6d3106e10b6a4525993d185a1443d9a125186960e028eabfdd8d76cf70a3a7e3100180122cc010801100118012240851fc9542342321af63ecbba7d3ece545f2a42bad01ba32cff5535b18e54b6d3106e10b6a4525993d185a1443d9a125186960e028eabfdd8d76cf70a3a7e31002a40851fc9542342321af63ecbba7d3ece545f2a42bad01ba32cff5535b18e54b6d3106e10b6a4525993d185a1443d9a125186960e028eabfdd8d76cf70a3a7e31003240851fc9542342321af63ecbba7d3ece545f2a42bad01ba32cff5535b18e54b6d3106e10b6a4525993d185a1443d9a125186960e028eabfdd8d76cf70a3a7e31002801',
},
{
name: 'TxRequest',
message: {
TxRequest: {
fields: {
request_type: {
type: 'RequestType',
id: 1,
},
details: {
type: 'TxRequestDetailsType',
id: 2,
},
serialized: {
type: 'TxRequestSerializedType',
id: 3,
},
},
nested: {
RequestType: {
values: {
TXINPUT: 0,
TXOUTPUT: 1,
TXMETA: 2,
TXFINISHED: 3,
TXEXTRADATA: 4,
TXORIGINPUT: 5,
TXORIGOUTPUT: 6,
},
},
TxRequestDetailsType: {
fields: {
request_index: {
type: 'uint32',
id: 1,
},
tx_hash: {
type: 'bytes',
id: 2,
},
extra_data_len: {
type: 'uint32',
id: 3,
},
extra_data_offset: {
type: 'uint32',
id: 4,
},
},
},
TxRequestSerializedType: {
fields: {
signature_index: {
type: 'uint32',
id: 1,
},
signature: {
type: 'bytes',
id: 2,
},
serialized_tx: {
type: 'bytes',
id: 3,
},
},
},
},
},
},
in: {
request_type: 0,
details: { request_index: 0 },
serialized: {
serialized_tx:
'851fc9542342321af63ecbba7d3ece545f2a42bad01ba32cff5535b18e54b6d3106e10b6a4525993d185a1443d9a125186960e028eabfdd8d76cf70a3a7e3100',
},
},
encoded:
'0800120208001a421a40851fc9542342321af63ecbba7d3ece545f2a42bad01ba32cff5535b18e54b6d3106e10b6a4525993d185a1443d9a125186960e028eabfdd8d76cf70a3a7e3100',
out: {
request_type: 'TXINPUT',
details: {
request_index: 0,
tx_hash: null,
extra_data_len: null,
extra_data_offset: null,
},
serialized: {
serialized_tx:
'851fc9542342321af63ecbba7d3ece545f2a42bad01ba32cff5535b18e54b6d3106e10b6a4525993d185a1443d9a125186960e028eabfdd8d76cf70a3a7e3100',
signature: null,
signature_index: null,
},
},
},
{
// taken from TrezorConnect fixtures signTransactionsMultisig.js. There is interesting part signatures: ['', '', ''];
name: 'MultisigRedeemScriptType',
message: {
HDNodeType,
MultisigRedeemScriptType,
},
in: {
pubkeys: [
{
node: {
depth: 4,
child_num: 2147483648,
fingerprint: 2559962404,
public_key:
'02d598ec0f8f418c80859b690e8ee731e2bf7c8e2233d7fa722249bc3f27a65151',
chain_code:
'fd5fd24c06088bce57f3d817df206d0891adf5a77f5391bdc12793ef1917460e',
},
address_n: [0, 0],
},
{
node: {
depth: 4,
child_num: 2147483648,
fingerprint: 3563901430,
public_key:
'03e2a1f110b6e42de5bcf7a15881c66e2455fb62137e55678692a5f690fc8de10f',
chain_code:
'ca9268e9c323cfceb971ee96c418a91b2f3415dfbb0dc1d11dd8fcdff73a9ab9',
},
address_n: [0, 0],
},
{
node: {
depth: 4,
child_num: 2147483648,
fingerprint: 598174955,
public_key:
'032b9bdd9510f75f4d32631ffe11a56b11d332c8c0f0e0801b686f6eec806e7a2f',
chain_code:
'267ba0b69f9b0c9aa6add7d7162ff5ac675aa420c8d7a468778a6630d5c82f60',
},
address_n: [0, 0],
},
],
signatures: ['', '', ''],
m: 2,
},
encoded:
'0a590a53080410a4dad7c4091880808080082220fd5fd24c06088bce57f3d817df206d0891adf5a77f5391bdc12793ef1917460e322102d598ec0f8f418c80859b690e8ee731e2bf7c8e2233d7fa722249bc3f27a65151100010000a590a53080410f6a3b3a30d1880808080082220ca9268e9c323cfceb971ee96c418a91b2f3415dfbb0dc1d11dd8fcdff73a9ab9322103e2a1f110b6e42de5bcf7a15881c66e2455fb62137e55678692a5f690fc8de10f100010000a590a53080410ebd99d9d021880808080082220267ba0b69f9b0c9aa6add7d7162ff5ac675aa420c8d7a468778a6630d5c82f603221032b9bdd9510f75f4d32631ffe11a56b11d332c8c0f0e0801b686f6eec806e7a2f100010001200120012001802',
out: {
// additional field. todo: not sure if shouldn't be omitted
address_n: [],
// additional field. todo: not sure if shouldn't be omitted
nodes: [],
pubkeys: [
{
node: {
depth: 4,
child_num: 2147483648,
fingerprint: 2559962404,
public_key:
'02d598ec0f8f418c80859b690e8ee731e2bf7c8e2233d7fa722249bc3f27a65151',
chain_code:
'fd5fd24c06088bce57f3d817df206d0891adf5a77f5391bdc12793ef1917460e',
// additional field to maintain backwards compatibility
private_key: null,
},
address_n: [0, 0],
},
{
node: {
depth: 4,
child_num: 2147483648,
fingerprint: 3563901430,
public_key:
'03e2a1f110b6e42de5bcf7a15881c66e2455fb62137e55678692a5f690fc8de10f',
chain_code:
'ca9268e9c323cfceb971ee96c418a91b2f3415dfbb0dc1d11dd8fcdff73a9ab9',
// additional field to maintain backwards compatibility
private_key: null,
},
address_n: [0, 0],
},
{
node: {
depth: 4,
child_num: 2147483648,
fingerprint: 598174955,
public_key:
'032b9bdd9510f75f4d32631ffe11a56b11d332c8c0f0e0801b686f6eec806e7a2f',
chain_code:
'267ba0b69f9b0c9aa6add7d7162ff5ac675aa420c8d7a468778a6630d5c82f60',
// additional field to maintain backwards compatibility
private_key: null,
},
address_n: [0, 0],
},
],
// point of interest.
// signatures are repeated bytes. if they sent from TrezorConnect as empty strings, encoding them as bytes makes trezor not accept this message
signatures: ['', '', ''],
m: 2,
},
},
{
name: 'Features',
message: {
SafetyCheckLevel: {
values: {
Strict: 0,
PromptAlways: 1,
PromptTemporarily: 2,
},
},
Features: {
fields: {
capabilities: {
rule: 'repeated',
type: 'Capability',
id: 30,
options: {
packed: false,
},
},
safety_checks: {
type: 'SafetyCheckLevel',
id: 37,
},
},
nested: {
Capability: {
options: {
'(has_bitcoin_only_values)': true,
},
values: {
Capability_Bitcoin: 1,
Capability_Bitcoin_like: 2,
},
},
},
},
},
in: { capabilities: ['Capability_Bitcoin'], safety_checks: 'Strict' },
encoded: 'f00101a80200',
out: { capabilities: ['Capability_Bitcoin'], safety_checks: 'Strict' },
},
{
name: 'CardanoTxWitnessRequest',
message: {
CardanoTxWitnessRequest: {
fields: {
path: {
rule: 'repeated',
type: 'uint32',
id: 1,
options: {
packed: false,
},
},
},
},
},
in: {
path: [2147485500, 2147485463, 2147483648, 2, 0],
},
encoded: '08bc8e80800808978e80800808808080800808020800',
out: {
path: [2147485500, 2147485463, 2147483648, 2, 0],
},
},
{
name: 'TxAckPrevExtraData',
message: {
TxAckPrevExtraData: {
options: {
'(wire_type)': 22,
'(include_in_bitcoin_only)': true,
},
fields: {
tx: {
rule: 'required',
type: 'TxAckPrevExtraDataWrapper',
id: 1,
},
},
nested: {
TxAckPrevExtraDataWrapper: {
fields: {
extra_data_chunk: {
rule: 'required',
type: 'bytes',
id: 8,
},
},
},
},
},
},
in: {
tx: {
extra_data_chunk:
'851fc9542342321af63ecbba7d3ece545f2a42bad01ba32cff5535b18e54b6d3106e10b6a4525993d185a1443d9a125186960e028eabfdd8d76cf70a3a7e3100',
},
},
encoded:
'0a424240851fc9542342321af63ecbba7d3ece545f2a42bad01ba32cff5535b18e54b6d3106e10b6a4525993d185a1443d9a125186960e028eabfdd8d76cf70a3a7e3100',
out: {
tx: {
extra_data_chunk:
'851fc9542342321af63ecbba7d3ece545f2a42bad01ba32cff5535b18e54b6d3106e10b6a4525993d185a1443d9a125186960e028eabfdd8d76cf70a3a7e3100',
},
},
},
];
describe('Real messages', () => {
fixtures.forEach(f => {
describe(f.name, () => {
const Messages = ProtoBuf.Root.fromJSON({
// @ts-expect-error
nested: { messages: { nested: { ...f.message } } },
});
const Message = Messages.lookupType(`messages.${f.name}`);
test('encode and decode', () => {
// serialize
const encoded = encode(Message, f.in);
expect(encoded.toString('hex')).toEqual(f.encoded);
// deserialize
const decoded = decode(Message, encoded);
expect(decoded).toEqual(f.out ? f.out : f.in);
});
});
});
test('without Messages object', () => {
expect(() => {
// @ts-expect-error
encode(null, {});
}).toThrow();
});
});