UNPKG

@liskhq/lisk-codec

Version:

Implementation of decoder and encoder using Lisk JSON schema according to the Lisk protocol

128 lines (120 loc) 3.35 kB
/* * Copyright © 2023 Lisk Foundation * * See the LICENSE file at the top-level directory of this distribution * for licensing information. * * Unless otherwise agreed in a custom licensing agreement with the Lisk Foundation, * no part of this software, including this file, may be copied, modified, * propagated, or distributed except according to the terms contained in the * LICENSE file. * * Removal or modification of this copyright notice is prohibited. */ const { utils } = require('@liskhq/lisk-cryptography'); const { codec } = require('../dist-node'); const testSchema = { $id: '/lisk/transaction-mock', type: 'object', required: ['module', 'command', 'nonce', 'fee', 'senderPublicKey', 'params'], properties: { module: { dataType: 'string', fieldNumber: 1, minLength: 1, maxLength: 32, }, command: { dataType: 'string', fieldNumber: 2, minLength: 1, maxLength: 32, }, nonce: { dataType: 'uint64', fieldNumber: 3, }, fee: { dataType: 'uint64', fieldNumber: 4, }, senderPublicKey: { dataType: 'bytes', fieldNumber: 5, minLength: 32, maxLength: 32, }, params: { dataType: 'bytes', fieldNumber: 6, }, signatures: { type: 'array', items: { dataType: 'bytes', }, fieldNumber: 7, }, }, }; function mutateRandomByte(buffer) { const mutationType = Math.random(); // Change a random byte if (mutationType < 0.33) { const index = Math.floor(Math.random() * buffer.length); const mutation = utils.getRandomBytes(1)[0]; buffer[index] = mutation; } // Add a random byte else if (mutationType < 0.66) { const index = Math.floor(Math.random() * (buffer.length + 1)); const mutation = utils.getRandomBytes(1); buffer = Buffer.concat([buffer.subarray(0, index), mutation, buffer.subarray(index)]); } // Remove a byte else { if (buffer.length === 1) { return buffer; // Can't remove byte from buffer of length 1 } const index = Math.floor(Math.random() * buffer.length); buffer = Buffer.concat([buffer.subarray(0, index), buffer.subarray(index + 1)]); } return buffer; } let successCounter = 0; let totalCounter = 100000; while (true) { // get random bytes length between 0 - 100 let original = codec.encode(testSchema, { module: (Math.random() + 1).toString(36).substring(7), command: (Math.random() + 1).toString(36).substring(7), nonce: BigInt(Math.floor(Math.random() * 10000000)), fee: BigInt(Math.floor(Math.random() * 10000000)), senderPublicKey: utils.getRandomBytes(32), params: utils.getRandomBytes(10), signatures: new Array(Math.floor(Math.random() * 3)) .fill(0) .map(() => utils.getRandomBytes(64)), }); for (let i = 0; i < totalCounter; i++) { try { original = mutateRandomByte(original); const decodedObj = codec.decode(testSchema, original); const reEncoded = codec.encode(testSchema, decodedObj); if (!reEncoded.equals(original)) { console.error('Fail to satisfy encode(decode(val)) == val', { original: original.toString('hex'), reEncoded: reEncoded.toString('hex'), decodedObj, }); process.exit(1); } successCounter += 1; } catch (error) { // console.log(error) // expected } } console.log(`Checked value for ${totalCounter}. Successfully validated ${successCounter}`); successCounter = 0; }