UNPKG

@mavrykdynamics/taquito-local-forging

Version:

Provide local forging functionality to be with taquito

516 lines (515 loc) 23.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.burnLimitDecoder = exports.burnLimitEncoder = exports.entrypointNameDecoder = exports.entrypointNameEncoder = exports.blockPayloadHashDecoder = exports.blockPayloadHashEncoder = exports.valueParameterDecoder = exports.valueParameterEncoder = exports.parametersEncoder = exports.entrypointEncoder = exports.parametersDecoder = exports.entrypointDecoder = exports.zarithDecoder = exports.zarithEncoder = exports.smartRollupCommitmentHashDecoder = exports.smartContractAddressDecoder = exports.smartRollupAddressDecoder = exports.addressDecoder = exports.smartRollupCommitmentHashEncoder = exports.publicKeyDecoder = exports.smartContractAddressEncoder = exports.smartRollupAddressEncoder = exports.addressEncoder = exports.publicKeyEncoder = exports.publicKeyHashesEncoder = exports.publicKeyHashEncoder = exports.delegateDecoder = exports.boolDecoder = exports.int16Decoder = exports.int16Encoder = exports.int32Decoder = exports.int32Encoder = exports.delegateEncoder = exports.pvmKindDecoder = exports.pvmKindEncoder = exports.ballotDecoder = exports.ballotEncoder = exports.proposalsEncoder = exports.proposalsDecoder = exports.proposalDecoder = exports.proposalEncoder = exports.boolEncoder = exports.mv1Encoder = exports.branchEncoder = exports.publicKeyHashesDecoder = exports.publicKeyHashDecoder = exports.branchDecoder = exports.mv1Decoder = exports.prefixDecoder = exports.prefixEncoder = void 0; exports.slotHeaderDecoder = exports.slotHeaderEncoder = exports.dalCommitmentDecoder = exports.dalCommitmentEncoder = exports.smartRollupMessageDecoder = exports.smartRollupMessageEncoder = exports.paddedBytesDecoder = exports.paddedBytesEncoder = exports.depositsLimitDecoder = exports.depositsLimitEncoder = void 0; const taquito_utils_1 = require("@mavrykdynamics/taquito-utils"); const errors_1 = require("./errors"); const bignumber_js_1 = require("bignumber.js"); const constants_1 = require("./constants"); const codec_1 = require("./michelson/codec"); const uint8array_consumer_1 = require("./uint8array-consumer"); const utils_1 = require("./utils"); const taquito_core_1 = require("@mavrykdynamics/taquito-core"); // https://protocol.mavryk.org/shell/p2p_api.html specifies data types and structure for forging const prefixEncoder = (prefix) => (str) => { return (0, taquito_utils_1.buf2hex)(Buffer.from((0, taquito_utils_1.b58cdecode)(str, taquito_utils_1.prefix[prefix]))); }; exports.prefixEncoder = prefixEncoder; const prefixDecoder = (pre) => (str) => { const val = str.consume(taquito_utils_1.prefixLength[pre]); return (0, taquito_utils_1.b58cencode)(val, taquito_utils_1.prefix[pre]); }; exports.prefixDecoder = prefixDecoder; exports.mv1Decoder = (0, exports.prefixDecoder)(taquito_utils_1.Prefix.MV1); exports.branchDecoder = (0, exports.prefixDecoder)(taquito_utils_1.Prefix.B); const publicKeyHashDecoder = (val) => { const prefix = val.consume(1); if (prefix[0] === 0x00) { return (0, exports.prefixDecoder)(taquito_utils_1.Prefix.MV1)(val); } else if (prefix[0] === 0x01) { return (0, exports.prefixDecoder)(taquito_utils_1.Prefix.MV2)(val); } else if (prefix[0] === 0x02) { return (0, exports.prefixDecoder)(taquito_utils_1.Prefix.MV3)(val); } }; exports.publicKeyHashDecoder = publicKeyHashDecoder; const publicKeyHashesDecoder = (val) => { if (!(0, exports.boolDecoder)(val)) { return undefined; } const publicKeyHashes = []; val.consume(4); while (val.length() > 0) { publicKeyHashes.push((0, exports.publicKeyHashDecoder)(val)); } return publicKeyHashes; }; exports.publicKeyHashesDecoder = publicKeyHashesDecoder; exports.branchEncoder = (0, exports.prefixEncoder)(taquito_utils_1.Prefix.B); exports.mv1Encoder = (0, exports.prefixEncoder)(taquito_utils_1.Prefix.MV1); const boolEncoder = (bool) => (bool ? 'ff' : '00'); exports.boolEncoder = boolEncoder; const proposalEncoder = (proposal) => { return (0, exports.prefixEncoder)(taquito_utils_1.Prefix.P)(proposal); }; exports.proposalEncoder = proposalEncoder; const proposalDecoder = (proposal) => { return (0, exports.prefixDecoder)(taquito_utils_1.Prefix.P)(proposal); }; exports.proposalDecoder = proposalDecoder; const proposalsDecoder = (proposal) => { const proposals = []; proposal.consume(4); while (proposal.length() > 0) { proposals.push((0, exports.proposalDecoder)(proposal)); } return proposals; }; exports.proposalsDecoder = proposalsDecoder; const proposalsEncoder = (proposals) => { return (0, utils_1.pad)(32 * proposals.length) + proposals.map((x) => (0, exports.proposalEncoder)(x)).join(''); }; exports.proposalsEncoder = proposalsEncoder; const ballotEncoder = (ballot) => { switch (ballot) { case 'yay': return '00'; case 'nay': return '01'; case 'pass': return '02'; default: throw new errors_1.InvalidBallotValueError(ballot); } }; exports.ballotEncoder = ballotEncoder; const ballotDecoder = (ballot) => { const value = ballot.consume(1); switch (value[0]) { case 0x00: return 'yay'; case 0x01: return 'nay'; case 0x02: return 'pass'; default: throw new errors_1.DecodeBallotValueError(value[0].toString()); } }; exports.ballotDecoder = ballotDecoder; const pvmKindEncoder = (pvm) => { switch (pvm) { case 'arith': return '00'; case 'wasm_2_0_0': return '01'; case 'riscv': return '02'; default: throw new errors_1.UnsupportedPvmKindError(pvm); } }; exports.pvmKindEncoder = pvmKindEncoder; const pvmKindDecoder = (pvm) => { const value = pvm.consume(1); switch (value[0]) { case 0x00: return 'arith'; case 0x01: return 'wasm_2_0_0'; case 0x02: return 'riscv'; default: throw new errors_1.DecodePvmKindError(value[0].toString()); } }; exports.pvmKindDecoder = pvmKindDecoder; const delegateEncoder = (val) => { if (val) { return (0, exports.boolEncoder)(true) + (0, exports.publicKeyHashEncoder)(val); } else { return (0, exports.boolEncoder)(false); } }; exports.delegateEncoder = delegateEncoder; const int32Encoder = (val) => { const num = parseInt(String(val), 10); const byte = []; for (let i = 0; i < 4; i++) { const shiftBy = (4 - (i + 1)) * 8; byte.push((num & (0xff << shiftBy)) >> shiftBy); } return Buffer.from(byte).toString('hex'); }; exports.int32Encoder = int32Encoder; const int32Decoder = (val) => { const num = val.consume(4); let finalNum = 0; for (let i = 0; i < num.length; i++) { finalNum = finalNum | (num[i] << ((num.length - (i + 1)) * 8)); } return finalNum; }; exports.int32Decoder = int32Decoder; const int16Encoder = (val) => { const num = parseInt(String(val), 10); const byte = []; for (let i = 0; i < 2; i++) { const shiftBy = (2 - (i + 1)) * 8; byte.push((num & (0xff << shiftBy)) >> shiftBy); } return Buffer.from(byte).toString('hex'); }; exports.int16Encoder = int16Encoder; const int16Decoder = (val) => { const num = val.consume(2); let finalNum = 0; for (let i = 0; i < num.length; i++) { finalNum = finalNum | (num[i] << ((num.length - (i + 1)) * 8)); } return finalNum; }; exports.int16Decoder = int16Decoder; const boolDecoder = (val) => { const bool = val.consume(1); return bool[0] === 0xff; }; exports.boolDecoder = boolDecoder; const delegateDecoder = (val) => { const hasDelegate = (0, exports.boolDecoder)(val); if (hasDelegate) { return (0, exports.publicKeyHashDecoder)(val); } }; exports.delegateDecoder = delegateDecoder; const publicKeyHashEncoder = (val) => { const pubkeyPrefix = val.substring(0, 3); switch (pubkeyPrefix) { case taquito_utils_1.Prefix.MV1: return '00' + (0, exports.prefixEncoder)(taquito_utils_1.Prefix.MV1)(val); case taquito_utils_1.Prefix.MV2: return '01' + (0, exports.prefixEncoder)(taquito_utils_1.Prefix.MV2)(val); case taquito_utils_1.Prefix.MV3: return '02' + (0, exports.prefixEncoder)(taquito_utils_1.Prefix.MV3)(val); case taquito_utils_1.Prefix.MV4: return '03' + (0, exports.prefixEncoder)(taquito_utils_1.Prefix.MV4)(val); default: throw new taquito_utils_1.InvalidKeyHashError(val, (0, taquito_utils_1.invalidDetail)(taquito_utils_1.ValidationResult.NO_PREFIX_MATCHED) + ` expecting one for the following "${taquito_utils_1.Prefix.MV1}", "${taquito_utils_1.Prefix.MV2}", "${taquito_utils_1.Prefix.MV3}" or "${taquito_utils_1.Prefix.MV4}".`); } }; exports.publicKeyHashEncoder = publicKeyHashEncoder; const publicKeyHashesEncoder = (val) => { if (!val) { return (0, exports.boolEncoder)(false); } if (val.length === 0) { return (0, exports.boolEncoder)(true) + (0, utils_1.pad)(0); } const publicKeyHashes = val.reduce((prev, curr) => { return prev + (0, exports.publicKeyHashEncoder)(curr); }, ''); return (0, exports.boolEncoder)(true) + (0, utils_1.pad)(publicKeyHashes.length / 2) + publicKeyHashes; }; exports.publicKeyHashesEncoder = publicKeyHashesEncoder; const publicKeyEncoder = (val) => { const pubkeyPrefix = val.substring(0, 4); switch (pubkeyPrefix) { case taquito_utils_1.Prefix.EDPK: return '00' + (0, exports.prefixEncoder)(taquito_utils_1.Prefix.EDPK)(val); case taquito_utils_1.Prefix.SPPK: return '01' + (0, exports.prefixEncoder)(taquito_utils_1.Prefix.SPPK)(val); case taquito_utils_1.Prefix.P2PK: return '02' + (0, exports.prefixEncoder)(taquito_utils_1.Prefix.P2PK)(val); default: throw new taquito_utils_1.InvalidPublicKeyError(val, (0, taquito_utils_1.invalidDetail)(taquito_utils_1.ValidationResult.NO_PREFIX_MATCHED) + ` expecting one of the following '${taquito_utils_1.Prefix.EDPK}', '${taquito_utils_1.Prefix.SPPK}', '${taquito_utils_1.Prefix.P2PK}' or '${taquito_utils_1.Prefix.BLPK}'.`); } }; exports.publicKeyEncoder = publicKeyEncoder; const addressEncoder = (val) => { const pubkeyPrefix = val.substring(0, 3); switch (pubkeyPrefix) { case taquito_utils_1.Prefix.MV1: case taquito_utils_1.Prefix.MV2: case taquito_utils_1.Prefix.MV3: case taquito_utils_1.Prefix.MV4: return '00' + (0, exports.publicKeyHashEncoder)(val); case taquito_utils_1.Prefix.KT1: return '01' + (0, exports.prefixEncoder)(taquito_utils_1.Prefix.KT1)(val) + '00'; default: throw new taquito_core_1.InvalidAddressError(val, (0, taquito_utils_1.invalidDetail)(taquito_utils_1.ValidationResult.NO_PREFIX_MATCHED) + ` expecting one of the following prefix '${taquito_utils_1.Prefix.MV1}', ${taquito_utils_1.Prefix.MV2}', '${taquito_utils_1.Prefix.MV3}', '${taquito_utils_1.Prefix.MV4}' or '${taquito_utils_1.Prefix.KT1}'.`); } }; exports.addressEncoder = addressEncoder; const smartRollupAddressEncoder = (val) => { if (val.substring(0, 3) !== taquito_utils_1.Prefix.SR1) { throw new errors_1.InvalidSmartRollupAddressError(val, (0, taquito_utils_1.invalidDetail)(taquito_utils_1.ValidationResult.NO_PREFIX_MATCHED) + ` expecting prefix '${taquito_utils_1.Prefix.SR1}'.`); } return (0, exports.prefixEncoder)(taquito_utils_1.Prefix.SR1)(val); }; exports.smartRollupAddressEncoder = smartRollupAddressEncoder; const smartContractAddressEncoder = (val) => { const prefix = val.substring(0, 3); if (prefix === taquito_utils_1.Prefix.KT1) { return '01' + (0, exports.prefixEncoder)(taquito_utils_1.Prefix.KT1)(val) + '00'; } throw new taquito_core_1.InvalidContractAddressError(val, (0, taquito_utils_1.invalidDetail)(taquito_utils_1.ValidationResult.NO_PREFIX_MATCHED) + ` expecting prefix '${taquito_utils_1.Prefix.KT1}'.`); }; exports.smartContractAddressEncoder = smartContractAddressEncoder; const publicKeyDecoder = (val) => { const preamble = val.consume(1); switch (preamble[0]) { case 0x00: return (0, exports.prefixDecoder)(taquito_utils_1.Prefix.EDPK)(val); case 0x01: return (0, exports.prefixDecoder)(taquito_utils_1.Prefix.SPPK)(val); case 0x02: return (0, exports.prefixDecoder)(taquito_utils_1.Prefix.P2PK)(val); default: throw new taquito_utils_1.InvalidPublicKeyError(val.toString(), (0, taquito_utils_1.invalidDetail)(taquito_utils_1.ValidationResult.NO_PREFIX_MATCHED)); } }; exports.publicKeyDecoder = publicKeyDecoder; const smartRollupCommitmentHashEncoder = (val) => { const prefix = val.substring(0, 4); if (prefix === taquito_utils_1.Prefix.SRC1) { return (0, exports.prefixEncoder)(taquito_utils_1.Prefix.SRC1)(val); } throw new errors_1.InvalidSmartRollupCommitmentHashError(val, (0, taquito_utils_1.invalidDetail)(taquito_utils_1.ValidationResult.NO_PREFIX_MATCHED) + ` expecting prefix '${taquito_utils_1.Prefix.SRC1}'`); }; exports.smartRollupCommitmentHashEncoder = smartRollupCommitmentHashEncoder; const addressDecoder = (val) => { const preamble = val.consume(1); switch (preamble[0]) { case 0x00: return (0, exports.publicKeyHashDecoder)(val); case 0x01: { const address = (0, exports.prefixDecoder)(taquito_utils_1.Prefix.KT1)(val); val.consume(1); return address; } default: throw new taquito_core_1.InvalidAddressError(val.toString(), ': Unable to decode.'); } }; exports.addressDecoder = addressDecoder; const smartRollupAddressDecoder = (val) => { const address = (0, exports.prefixDecoder)(taquito_utils_1.Prefix.SR1)(val); if (address.substring(0, 3) !== taquito_utils_1.Prefix.SR1) { throw new errors_1.InvalidSmartRollupAddressError(address, (0, taquito_utils_1.invalidDetail)(taquito_utils_1.ValidationResult.NO_PREFIX_MATCHED) + ` expecting prefix '${taquito_utils_1.Prefix.SR1}'.`); } return address; }; exports.smartRollupAddressDecoder = smartRollupAddressDecoder; const smartContractAddressDecoder = (val) => { const preamble = val.consume(1); if (preamble[0] === 0x01) { const scAddress = (0, exports.prefixDecoder)(taquito_utils_1.Prefix.KT1)(val); val.consume(1); return scAddress; } throw new taquito_core_1.InvalidContractAddressError(val.toString(), (0, taquito_utils_1.invalidDetail)(taquito_utils_1.ValidationResult.NO_PREFIX_MATCHED)); }; exports.smartContractAddressDecoder = smartContractAddressDecoder; const smartRollupCommitmentHashDecoder = (val) => { const address = (0, exports.prefixDecoder)(taquito_utils_1.Prefix.SRC1)(val); if (address.substring(0, 4) !== taquito_utils_1.Prefix.SRC1) { throw new errors_1.InvalidSmartRollupCommitmentHashError(address, (0, taquito_utils_1.invalidDetail)(taquito_utils_1.ValidationResult.NO_PREFIX_MATCHED) + ` expecting prefix '${taquito_utils_1.Prefix.SRC1}'`); } return address; }; exports.smartRollupCommitmentHashDecoder = smartRollupCommitmentHashDecoder; const zarithEncoder = (n) => { const fn = []; let nn = new bignumber_js_1.default(n, 10); if (nn.isNaN()) { throw new TypeError(`Invalid zarith number ${n}`); } // eslint-disable-next-line no-constant-condition while (true) { if (nn.lt(128)) { if (nn.lt(16)) fn.push('0'); fn.push(nn.toString(16)); break; } else { let b = nn.mod(128); nn = nn.minus(b); nn = nn.dividedBy(128); b = b.plus(128); fn.push(b.toString(16)); } } return fn.join(''); }; exports.zarithEncoder = zarithEncoder; const zarithDecoder = (n) => { let mostSignificantByte = 0; while (mostSignificantByte < n.length() && (n.get(mostSignificantByte) & 128) !== 0) { mostSignificantByte += 1; } let num = new bignumber_js_1.default(0); for (let i = mostSignificantByte; i >= 0; i -= 1) { const tmp = n.get(i) & 0x7f; num = num.multipliedBy(128); num = num.plus(tmp); } n.consume(mostSignificantByte + 1); return new bignumber_js_1.default(num).toString(); }; exports.zarithDecoder = zarithDecoder; const entrypointDecoder = (value) => { const preamble = (0, utils_1.pad)(value.consume(1)[0], 2); if (preamble in constants_1.entrypointMapping) { return constants_1.entrypointMapping[preamble]; } else { const entry = (0, codec_1.extractRequiredLen)(value, 1); const entrypoint = Buffer.from(entry).toString('utf8'); if (entrypoint.length > constants_1.ENTRYPOINT_MAX_LENGTH) { throw new errors_1.OversizedEntryPointError(entrypoint); } return entrypoint; } }; exports.entrypointDecoder = entrypointDecoder; const parametersDecoder = (val) => { const preamble = val.consume(1); if (preamble[0] === 0x00) { return; } else { const encodedEntrypoint = (0, exports.entrypointDecoder)(val); const params = (0, codec_1.extractRequiredLen)(val); const parameters = (0, codec_1.valueDecoder)(new uint8array_consumer_1.Uint8ArrayConsumer(params)); return { entrypoint: encodedEntrypoint, value: parameters, }; } }; exports.parametersDecoder = parametersDecoder; const entrypointEncoder = (entrypoint) => { if (entrypoint in constants_1.entrypointMappingReverse) { return `${constants_1.entrypointMappingReverse[entrypoint]}`; } else { if (entrypoint.length > constants_1.ENTRYPOINT_MAX_LENGTH) { throw new errors_1.OversizedEntryPointError(entrypoint); } const value = { string: entrypoint }; return `ff${(0, codec_1.valueEncoder)(value).slice(8)}`; } }; exports.entrypointEncoder = entrypointEncoder; const parametersEncoder = (val) => { if (!val || (val.entrypoint === 'default' && 'prim' in val.value && val.value.prim === 'Unit')) { return '00'; } const encodedEntrypoint = (0, exports.entrypointEncoder)(val.entrypoint); const parameters = (0, codec_1.valueEncoder)(val.value); const length = (0, utils_1.pad)(parameters.length / 2); return `ff${encodedEntrypoint}${length}${parameters}`; }; exports.parametersEncoder = parametersEncoder; const valueParameterEncoder = (value) => { const valueEncoded = (0, codec_1.valueEncoder)(value); return `${(0, utils_1.pad)(valueEncoded.length / 2)}${valueEncoded}`; }; exports.valueParameterEncoder = valueParameterEncoder; const valueParameterDecoder = (val) => { const value = (0, codec_1.extractRequiredLen)(val); return (0, codec_1.valueDecoder)(new uint8array_consumer_1.Uint8ArrayConsumer(value)); }; exports.valueParameterDecoder = valueParameterDecoder; exports.blockPayloadHashEncoder = (0, exports.prefixEncoder)(taquito_utils_1.Prefix.VH); exports.blockPayloadHashDecoder = (0, exports.prefixDecoder)(taquito_utils_1.Prefix.VH); const entrypointNameEncoder = (entrypoint) => { const value = { string: entrypoint }; return `${(0, codec_1.valueEncoder)(value).slice(2)}`; }; exports.entrypointNameEncoder = entrypointNameEncoder; const entrypointNameDecoder = (val) => { const entry = (0, codec_1.extractRequiredLen)(val); return Buffer.from(entry).toString('utf8'); }; exports.entrypointNameDecoder = entrypointNameDecoder; const burnLimitEncoder = (val) => { return !val ? '00' : `ff${(0, exports.zarithEncoder)(val)}`; }; exports.burnLimitEncoder = burnLimitEncoder; const burnLimitDecoder = (value) => { const prefix = value.consume(1); if (Buffer.from(prefix).toString('hex') !== '00') { return (0, exports.zarithDecoder)(value); } }; exports.burnLimitDecoder = burnLimitDecoder; const depositsLimitEncoder = (val) => { return !val ? '00' : `ff${(0, exports.zarithEncoder)(val)}`; }; exports.depositsLimitEncoder = depositsLimitEncoder; const depositsLimitDecoder = (value) => { const prefix = value.consume(1); if (Buffer.from(prefix).toString('hex') !== '00') { return (0, exports.zarithDecoder)(value); } }; exports.depositsLimitDecoder = depositsLimitDecoder; const paddedBytesEncoder = (val, paddingLength = 8) => { return `${(0, utils_1.pad)(val.length / 2, paddingLength)}${val}`; }; exports.paddedBytesEncoder = paddedBytesEncoder; const paddedBytesDecoder = (val) => { const value = (0, codec_1.extractRequiredLen)(val); return Buffer.from(value).toString('hex'); }; exports.paddedBytesDecoder = paddedBytesDecoder; const smartRollupMessageEncoder = (val) => { const message = val.reduce((prev, curr) => { return prev + `${(0, utils_1.pad)(curr.length / 2)}${curr}`; }, ''); return `${(0, utils_1.pad)(message.length / 2)}${message}`; }; exports.smartRollupMessageEncoder = smartRollupMessageEncoder; const smartRollupMessageDecoder = (val) => { const valueArray = (0, codec_1.extractRequiredLen)(val); const ret = (0, codec_1.stripLengthPrefixFromBytes)(new uint8array_consumer_1.Uint8ArrayConsumer(valueArray)); return ret.map((value) => Buffer.from(value).toString('hex')); }; exports.smartRollupMessageDecoder = smartRollupMessageDecoder; const dalCommitmentEncoder = (val) => { const prefix = val.substring(0, 2); if (prefix === taquito_utils_1.Prefix.SH) { return (0, exports.prefixEncoder)(taquito_utils_1.Prefix.SH)(val); } throw new errors_1.InvalidDalCommitmentError(val, (0, taquito_utils_1.invalidDetail)(taquito_utils_1.ValidationResult.NO_PREFIX_MATCHED) + ` expecting prefix '${taquito_utils_1.Prefix.SH}'`); }; exports.dalCommitmentEncoder = dalCommitmentEncoder; const dalCommitmentDecoder = (val) => { const commitment = (0, exports.prefixDecoder)(taquito_utils_1.Prefix.SH)(val); if (commitment.substring(0, 2) !== taquito_utils_1.Prefix.SH) { throw new errors_1.InvalidDalCommitmentError(commitment, (0, taquito_utils_1.invalidDetail)(taquito_utils_1.ValidationResult.NO_PREFIX_MATCHED) + ` expecting prefix '${taquito_utils_1.Prefix.SH}'`); } return commitment; }; exports.dalCommitmentDecoder = dalCommitmentDecoder; const slotHeaderEncoder = (val) => { return (0, utils_1.pad)(val.slot_index, 2) + (0, exports.dalCommitmentEncoder)(val.commitment) + val.commitment_proof; }; exports.slotHeaderEncoder = slotHeaderEncoder; const slotHeaderDecoder = (val) => { const preamble = val.consume(1); return { slot_index: Number(preamble[0].toString(10)), commitment: (0, exports.dalCommitmentDecoder)(val), commitment_proof: (0, utils_1.toHexString)(val.consume(96)), // rpcForger expect commitment_proof bytes to be len 96 }; }; exports.slotHeaderDecoder = slotHeaderDecoder;