From c06678bf2dd21ff9019c6d7a5d81d61d423ed1a7 Mon Sep 17 00:00:00 2001 From: AbigailDeng Date: Tue, 21 Mar 2023 11:52:19 +0800 Subject: [PATCH] feat: keccak --- package.json | 3 +- src/contract/contractMethod.js | 70 +++--- src/util/httpProvider.js | 1 + src/util/keccak.js | 21 ++ src/util/keccak/api.js | 49 ----- src/util/keccak/index.js | 26 --- src/util/keccak/keccak.js | 255 ---------------------- test/unit/contract/contractMethod.test.js | 87 ++++++-- test/unit/util/bloom.test.js | 23 +- test/unit/util/httpProvider.test.js | 1 + yarn.lock | 19 ++ 11 files changed, 162 insertions(+), 393 deletions(-) create mode 100644 src/util/keccak.js delete mode 100644 src/util/keccak/api.js delete mode 100644 src/util/keccak/index.js delete mode 100644 src/util/keccak/keccak.js diff --git a/package.json b/package.json index 326d8b09..08a6c8ce 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "test:browser:watch": "jest --config=jest.browser.config.js --watch", "test:node": "jest --config=jest.node.config.js", "test:node:watch": "jest --config=jest.node.config.js --watch", - "test:coverage": "jest --config=jest.browser.config.js --coverage" + "test:coverage": "jest --config=jest.browser.config.js ./test/unit/contract/contractMethod.test.js --coverage" }, "keywords": [ "aelf-web3" @@ -61,6 +61,7 @@ "hdkey": "^1.1.1", "isomorphic-fetch": "^3.0.0", "js-sha256": "^0.9.0", + "keccak": "^3.0.3", "query-string": "5.1.1", "randombytes": "^2.1.0", "readable-stream": "^3.6.0", diff --git a/src/contract/contractMethod.js b/src/contract/contractMethod.js index 60540ec0..b6d157bf 100644 --- a/src/contract/contractMethod.js +++ b/src/contract/contractMethod.js @@ -2,23 +2,20 @@ * @file contract method * @author atom-yang */ -import { - getTransaction, - Transaction -} from '../util/proto'; +import { getTransaction, Transaction } from '../util/proto'; import { transformArrayToMap, transformMapToArray, transform, INPUT_TRANSFORMERS, - OUTPUT_TRANSFORMERS + OUTPUT_TRANSFORMERS, } from '../util/transform'; import { isBoolean, isFunction, noop, uint8ArrayToHex, - unpackSpecifiedTypeData + unpackSpecifiedTypeData, } from '../util/utils'; import wallet from '../wallet'; @@ -61,7 +58,7 @@ export default class ContractMethod { } const result = unpackSpecifiedTypeData({ data: inputPacked, - dataType: this._inputType + dataType: this._inputType, }); let params = transform(this._inputType, result, OUTPUT_TRANSFORMERS); params = transformArrayToMap(this._inputType, params); @@ -74,7 +71,7 @@ export default class ContractMethod { } let result = unpackSpecifiedTypeData({ data: output, - dataType: this._outputType + dataType: this._outputType, }); result = transform(this._outputType, result, OUTPUT_TRANSFORMERS); result = transformArrayToMap(this._outputType, result); @@ -86,7 +83,9 @@ export default class ContractMethod { return null; } let params = transformMapToArray(this._outputType, result); + params = transform(this._outputType, params, INPUT_TRANSFORMERS); + const message = this._outputType.fromObject(params); return this._outputType.encode(message).finish(); } @@ -104,7 +103,9 @@ export default class ContractMethod { } prepareParametersAsync(args) { - const filterArgs = args.filter(arg => !isFunction(arg) && !isBoolean(arg.sync)); + const filterArgs = args.filter( + arg => !isFunction(arg) && !isBoolean(arg.sync) + ); const encoded = this.packInput(filterArgs[0]); return this._chain.getChainStatus().then(status => { @@ -114,18 +115,22 @@ export default class ContractMethod { } prepareParameters(args) { - const filterArgs = args.filter(arg => !isFunction(arg) && !isBoolean(arg.sync)); + const filterArgs = args.filter( + arg => !isFunction(arg) && !isBoolean(arg.sync) + ); const encoded = this.packInput(filterArgs[0]); const { BestChainHeight, BestChainHash } = this._chain.getChainStatus({ - sync: true + sync: true, }); return this.handleTransaction(BestChainHeight, BestChainHash, encoded); } prepareParametersWithBlockInfo(args) { - const filterArgs = args.filter(arg => !isFunction(arg) && !isBoolean(arg.sync)); + const filterArgs = args.filter( + arg => !isFunction(arg) && !isBoolean(arg.sync) + ); const encoded = this.packInput(filterArgs[0]); const { height, hash } = filterArgs[1]; // blockInfo @@ -138,7 +143,7 @@ export default class ContractMethod { if (argsObject.isSync) { const parameters = this.prepareParameters(args); return this._chain.sendTransaction(parameters, { - sync: true + sync: true, }); } // eslint-disable-next-line arrow-body-style @@ -151,22 +156,26 @@ export default class ContractMethod { const argsObject = this.extractArgumentsIntoObject(args); if (argsObject.isSync) { const parameters = this.prepareParameters(args); - return this.unpackOutput(this._chain.callReadOnly(parameters, { - sync: true - })); + return this.unpackOutput( + this._chain.callReadOnly(parameters, { + sync: true, + }) + ); } // eslint-disable-next-line arrow-body-style return this.prepareParametersAsync(args).then(parameters => { - return this._chain.callReadOnly(parameters, (error, result) => { - argsObject.callback(error, this.unpackOutput(result)); - }).then(this.unpackOutput); + return this._chain + .callReadOnly(parameters, (error, result) => { + argsObject.callback(error, this.unpackOutput(result)); + }) + .then(this.unpackOutput); }); } extractArgumentsIntoObject(args) { const result = { callback: noop, - isSync: false + isSync: false, }; if (args.length === 0) { // has no callback, default to be async mode @@ -176,7 +185,7 @@ export default class ContractMethod { result.callback = args[args.length - 1]; } args.forEach(arg => { - if (isBoolean((arg.sync))) { + if (isBoolean(arg.sync)) { result.isSync = arg.sync; } }); @@ -185,7 +194,9 @@ export default class ContractMethod { // getData(...args) { getSignedTx(...args) { - const filterArgs = args.filter(arg => !isFunction(arg) && !isBoolean(arg.sync)); + const filterArgs = args.filter( + arg => !isFunction(arg) && !isBoolean(arg.sync) + ); if (filterArgs[1]) { const { height, hash } = filterArgs[1]; // blockInfo @@ -199,11 +210,18 @@ export default class ContractMethod { } getRawTx(blockHeightInput, blockHashInput, packedInput) { - const rawTx = getTransaction(this._wallet.address, this._contractAddress, this._name, packedInput); + const rawTx = getTransaction( + this._wallet.address, + this._contractAddress, + this._name, + packedInput + ); rawTx.refBlockNumber = blockHeightInput; - const blockHash = blockHashInput.match(/^0x/) ? blockHashInput.substring(2) : blockHashInput; - rawTx.refBlockPrefix = (Buffer.from(blockHash, 'hex')).slice(0, 4); + const blockHash = blockHashInput.match(/^0x/) + ? blockHashInput.substring(2) + : blockHashInput; + rawTx.refBlockPrefix = Buffer.from(blockHash, 'hex').slice(0, 4); return rawTx; } @@ -214,7 +232,7 @@ export default class ContractMethod { method: 'broadcast_tx', callback, params, - format: this.unpackOutput + format: this.unpackOutput, }; } diff --git a/src/util/httpProvider.js b/src/util/httpProvider.js index 8b5db5dd..c4e7f3fa 100644 --- a/src/util/httpProvider.js +++ b/src/util/httpProvider.js @@ -13,6 +13,7 @@ let RequestLibrary = {}; let isFetch = false; if (process.env.RUNTIME_ENV === 'browser') { // For browsers use DOM Api XMLHttpRequest + // serviceworker without window and document, only with self // eslint-disable-next-line no-restricted-globals const _self = typeof self === 'object' ? self : {}; const _window = typeof window === 'object' ? window : _self; diff --git a/src/util/keccak.js b/src/util/keccak.js new file mode 100644 index 00000000..bd6ec839 --- /dev/null +++ b/src/util/keccak.js @@ -0,0 +1,21 @@ +const createKeccakHash = require('keccak'); + +const keccak = bits => str => { + let msg; + if (str.slice(0, 2) === '0x') { + msg = []; + for (let i = 2, l = str.length; i < l; i += 2) { + msg.push(parseInt(str.slice(i, i + 2), 16)); + } + msg = Buffer.from(msg); + } else { + msg = str; + } + const instance = createKeccakHash(`keccak${bits}`); + return `0x${instance.update(msg).digest('hex')}`; +}; + +export const keccak256 = keccak(256); +export const keccak512 = keccak(512); +export const keccak256s = keccak(256); +export const keccak512s = keccak(512); diff --git a/src/util/keccak/api.js b/src/util/keccak/api.js deleted file mode 100644 index a6ab1960..00000000 --- a/src/util/keccak/api.js +++ /dev/null @@ -1,49 +0,0 @@ -/* eslint-disable no-param-reassign */ -const { Transform } = require('readable-stream'); - -module.exports = KeccakState => class Keccak extends Transform { - constructor(rate, capacity, delimitedSuffix, hashBitLength, options) { - super(options); - - this._rate = rate; - this._capacity = capacity; - this._delimitedSuffix = delimitedSuffix; - this._hashBitLength = hashBitLength; - this._options = options; - - this._state = new KeccakState(); - this._state.initialize(rate, capacity); - this._finalized = false; - } - - update(data, encoding) { - if (!Buffer.isBuffer(data) && typeof data !== 'string') { - throw new TypeError('Data must be a string or a buffer'); - } - if (this._finalized) throw new Error('Digest already called'); - if (!Buffer.isBuffer(data)) data = Buffer.from(data, encoding); - - this._state.absorb(data); - - return this; - } - - digest(encoding) { - if (this._finalized) throw new Error('Digest already called'); - this._finalized = true; - - if (this._delimitedSuffix) { this._state.absorbLastFewBits(this._delimitedSuffix); } - let digest = this._state.squeeze(this._hashBitLength / 8); - if (encoding !== undefined) digest = digest.toString(encoding); - - this._resetState(); - - return digest; - } - - // remove result from memory - _resetState() { - this._state.initialize(this._rate, this._capacity); - return this; - } -}; diff --git a/src/util/keccak/index.js b/src/util/keccak/index.js deleted file mode 100644 index 29c3ad41..00000000 --- a/src/util/keccak/index.js +++ /dev/null @@ -1,26 +0,0 @@ -const createKeccak = require('./api'); -const KeccakState = require('./keccak'); - -const keccak = bits => str => { - let msg; - if (str.slice(0, 2) === '0x') { - msg = []; - for (let i = 2, l = str.length; i < l; i += 2) { msg.push(parseInt(str.slice(i, i + 2), 16)); } - msg = Buffer.from(msg); - } else { - msg = str; - } - let instance; - const Keccak = createKeccak(KeccakState); - if (bits === 256) { - instance = new Keccak(1088, 512, null, 256); - } else { - instance = new Keccak(576, 1024, null, 512); - } - return `0x${instance.update(msg).digest('hex')}`; -}; - -export const keccak256 = keccak(256); -export const keccak512 = keccak(512); -export const keccak256s = keccak(256); -export const keccak512s = keccak(512); diff --git a/src/util/keccak/keccak.js b/src/util/keccak/keccak.js deleted file mode 100644 index 84e7e84f..00000000 --- a/src/util/keccak/keccak.js +++ /dev/null @@ -1,255 +0,0 @@ -/* eslint-disable no-param-reassign */ -const P1600_ROUND_CONSTANTS = [ - 1, 0, 32898, 0, 32906, 2147483648, 2147516416, 2147483648, 32907, 0, - 2147483649, 0, 2147516545, 2147483648, 32777, 2147483648, 138, 0, 136, 0, - 2147516425, 0, 2147483658, 0, 2147516555, 0, 139, 2147483648, 32905, - 2147483648, 32771, 2147483648, 32770, 2147483648, 128, 2147483648, 32778, 0, - 2147483658, 2147483648, 2147516545, 2147483648, 32896, 2147483648, 2147483649, - 0, 2147516424, 2147483648, -]; - -const keccakState = { - p1600(s) { - for (let round = 0; round < 24; ++round) { - // theta - const lo0 = s[0] ^ s[10] ^ s[20] ^ s[30] ^ s[40]; - const hi0 = s[1] ^ s[11] ^ s[21] ^ s[31] ^ s[41]; - const lo1 = s[2] ^ s[12] ^ s[22] ^ s[32] ^ s[42]; - const hi1 = s[3] ^ s[13] ^ s[23] ^ s[33] ^ s[43]; - const lo2 = s[4] ^ s[14] ^ s[24] ^ s[34] ^ s[44]; - const hi2 = s[5] ^ s[15] ^ s[25] ^ s[35] ^ s[45]; - const lo3 = s[6] ^ s[16] ^ s[26] ^ s[36] ^ s[46]; - const hi3 = s[7] ^ s[17] ^ s[27] ^ s[37] ^ s[47]; - const lo4 = s[8] ^ s[18] ^ s[28] ^ s[38] ^ s[48]; - const hi4 = s[9] ^ s[19] ^ s[29] ^ s[39] ^ s[49]; - - let lo = lo4 ^ ((lo1 << 1) | (hi1 >>> 31)); - let hi = hi4 ^ ((hi1 << 1) | (lo1 >>> 31)); - const t1slo0 = s[0] ^ lo; - const t1shi0 = s[1] ^ hi; - const t1slo5 = s[10] ^ lo; - const t1shi5 = s[11] ^ hi; - const t1slo10 = s[20] ^ lo; - const t1shi10 = s[21] ^ hi; - const t1slo15 = s[30] ^ lo; - const t1shi15 = s[31] ^ hi; - const t1slo20 = s[40] ^ lo; - const t1shi20 = s[41] ^ hi; - lo = lo0 ^ ((lo2 << 1) | (hi2 >>> 31)); - hi = hi0 ^ ((hi2 << 1) | (lo2 >>> 31)); - const t1slo1 = s[2] ^ lo; - const t1shi1 = s[3] ^ hi; - const t1slo6 = s[12] ^ lo; - const t1shi6 = s[13] ^ hi; - const t1slo11 = s[22] ^ lo; - const t1shi11 = s[23] ^ hi; - const t1slo16 = s[32] ^ lo; - const t1shi16 = s[33] ^ hi; - const t1slo21 = s[42] ^ lo; - const t1shi21 = s[43] ^ hi; - lo = lo1 ^ ((lo3 << 1) | (hi3 >>> 31)); - hi = hi1 ^ ((hi3 << 1) | (lo3 >>> 31)); - const t1slo2 = s[4] ^ lo; - const t1shi2 = s[5] ^ hi; - const t1slo7 = s[14] ^ lo; - const t1shi7 = s[15] ^ hi; - const t1slo12 = s[24] ^ lo; - const t1shi12 = s[25] ^ hi; - const t1slo17 = s[34] ^ lo; - const t1shi17 = s[35] ^ hi; - const t1slo22 = s[44] ^ lo; - const t1shi22 = s[45] ^ hi; - lo = lo2 ^ ((lo4 << 1) | (hi4 >>> 31)); - hi = hi2 ^ ((hi4 << 1) | (lo4 >>> 31)); - const t1slo3 = s[6] ^ lo; - const t1shi3 = s[7] ^ hi; - const t1slo8 = s[16] ^ lo; - const t1shi8 = s[17] ^ hi; - const t1slo13 = s[26] ^ lo; - const t1shi13 = s[27] ^ hi; - const t1slo18 = s[36] ^ lo; - const t1shi18 = s[37] ^ hi; - const t1slo23 = s[46] ^ lo; - const t1shi23 = s[47] ^ hi; - lo = lo3 ^ ((lo0 << 1) | (hi0 >>> 31)); - hi = hi3 ^ ((hi0 << 1) | (lo0 >>> 31)); - const t1slo4 = s[8] ^ lo; - const t1shi4 = s[9] ^ hi; - const t1slo9 = s[18] ^ lo; - const t1shi9 = s[19] ^ hi; - const t1slo14 = s[28] ^ lo; - const t1shi14 = s[29] ^ hi; - const t1slo19 = s[38] ^ lo; - const t1shi19 = s[39] ^ hi; - const t1slo24 = s[48] ^ lo; - const t1shi24 = s[49] ^ hi; - - // rho & pi - const t2slo0 = t1slo0; - const t2shi0 = t1shi0; - const t2slo16 = (t1shi5 << 4) | (t1slo5 >>> 28); - const t2shi16 = (t1slo5 << 4) | (t1shi5 >>> 28); - const t2slo7 = (t1slo10 << 3) | (t1shi10 >>> 29); - const t2shi7 = (t1shi10 << 3) | (t1slo10 >>> 29); - const t2slo23 = (t1shi15 << 9) | (t1slo15 >>> 23); - const t2shi23 = (t1slo15 << 9) | (t1shi15 >>> 23); - const t2slo14 = (t1slo20 << 18) | (t1shi20 >>> 14); - const t2shi14 = (t1shi20 << 18) | (t1slo20 >>> 14); - const t2slo10 = (t1slo1 << 1) | (t1shi1 >>> 31); - const t2shi10 = (t1shi1 << 1) | (t1slo1 >>> 31); - const t2slo1 = (t1shi6 << 12) | (t1slo6 >>> 20); - const t2shi1 = (t1slo6 << 12) | (t1shi6 >>> 20); - const t2slo17 = (t1slo11 << 10) | (t1shi11 >>> 22); - const t2shi17 = (t1shi11 << 10) | (t1slo11 >>> 22); - const t2slo8 = (t1shi16 << 13) | (t1slo16 >>> 19); - const t2shi8 = (t1slo16 << 13) | (t1shi16 >>> 19); - const t2slo24 = (t1slo21 << 2) | (t1shi21 >>> 30); - const t2shi24 = (t1shi21 << 2) | (t1slo21 >>> 30); - const t2slo20 = (t1shi2 << 30) | (t1slo2 >>> 2); - const t2shi20 = (t1slo2 << 30) | (t1shi2 >>> 2); - const t2slo11 = (t1slo7 << 6) | (t1shi7 >>> 26); - const t2shi11 = (t1shi7 << 6) | (t1slo7 >>> 26); - const t2slo2 = (t1shi12 << 11) | (t1slo12 >>> 21); - const t2shi2 = (t1slo12 << 11) | (t1shi12 >>> 21); - const t2slo18 = (t1slo17 << 15) | (t1shi17 >>> 17); - const t2shi18 = (t1shi17 << 15) | (t1slo17 >>> 17); - const t2slo9 = (t1shi22 << 29) | (t1slo22 >>> 3); - const t2shi9 = (t1slo22 << 29) | (t1shi22 >>> 3); - const t2slo5 = (t1slo3 << 28) | (t1shi3 >>> 4); - const t2shi5 = (t1shi3 << 28) | (t1slo3 >>> 4); - const t2slo21 = (t1shi8 << 23) | (t1slo8 >>> 9); - const t2shi21 = (t1slo8 << 23) | (t1shi8 >>> 9); - const t2slo12 = (t1slo13 << 25) | (t1shi13 >>> 7); - const t2shi12 = (t1shi13 << 25) | (t1slo13 >>> 7); - const t2slo3 = (t1slo18 << 21) | (t1shi18 >>> 11); - const t2shi3 = (t1shi18 << 21) | (t1slo18 >>> 11); - const t2slo19 = (t1shi23 << 24) | (t1slo23 >>> 8); - const t2shi19 = (t1slo23 << 24) | (t1shi23 >>> 8); - const t2slo15 = (t1slo4 << 27) | (t1shi4 >>> 5); - const t2shi15 = (t1shi4 << 27) | (t1slo4 >>> 5); - const t2slo6 = (t1slo9 << 20) | (t1shi9 >>> 12); - const t2shi6 = (t1shi9 << 20) | (t1slo9 >>> 12); - const t2slo22 = (t1shi14 << 7) | (t1slo14 >>> 25); - const t2shi22 = (t1slo14 << 7) | (t1shi14 >>> 25); - const t2slo13 = (t1slo19 << 8) | (t1shi19 >>> 24); - const t2shi13 = (t1shi19 << 8) | (t1slo19 >>> 24); - const t2slo4 = (t1slo24 << 14) | (t1shi24 >>> 18); - const t2shi4 = (t1shi24 << 14) | (t1slo24 >>> 18); - - // chi - s[0] = t2slo0 ^ (~t2slo1 & t2slo2); - s[1] = t2shi0 ^ (~t2shi1 & t2shi2); - s[10] = t2slo5 ^ (~t2slo6 & t2slo7); - s[11] = t2shi5 ^ (~t2shi6 & t2shi7); - s[20] = t2slo10 ^ (~t2slo11 & t2slo12); - s[21] = t2shi10 ^ (~t2shi11 & t2shi12); - s[30] = t2slo15 ^ (~t2slo16 & t2slo17); - s[31] = t2shi15 ^ (~t2shi16 & t2shi17); - s[40] = t2slo20 ^ (~t2slo21 & t2slo22); - s[41] = t2shi20 ^ (~t2shi21 & t2shi22); - s[2] = t2slo1 ^ (~t2slo2 & t2slo3); - s[3] = t2shi1 ^ (~t2shi2 & t2shi3); - s[12] = t2slo6 ^ (~t2slo7 & t2slo8); - s[13] = t2shi6 ^ (~t2shi7 & t2shi8); - s[22] = t2slo11 ^ (~t2slo12 & t2slo13); - s[23] = t2shi11 ^ (~t2shi12 & t2shi13); - s[32] = t2slo16 ^ (~t2slo17 & t2slo18); - s[33] = t2shi16 ^ (~t2shi17 & t2shi18); - s[42] = t2slo21 ^ (~t2slo22 & t2slo23); - s[43] = t2shi21 ^ (~t2shi22 & t2shi23); - s[4] = t2slo2 ^ (~t2slo3 & t2slo4); - s[5] = t2shi2 ^ (~t2shi3 & t2shi4); - s[14] = t2slo7 ^ (~t2slo8 & t2slo9); - s[15] = t2shi7 ^ (~t2shi8 & t2shi9); - s[24] = t2slo12 ^ (~t2slo13 & t2slo14); - s[25] = t2shi12 ^ (~t2shi13 & t2shi14); - s[34] = t2slo17 ^ (~t2slo18 & t2slo19); - s[35] = t2shi17 ^ (~t2shi18 & t2shi19); - s[44] = t2slo22 ^ (~t2slo23 & t2slo24); - s[45] = t2shi22 ^ (~t2shi23 & t2shi24); - s[6] = t2slo3 ^ (~t2slo4 & t2slo0); - s[7] = t2shi3 ^ (~t2shi4 & t2shi0); - s[16] = t2slo8 ^ (~t2slo9 & t2slo5); - s[17] = t2shi8 ^ (~t2shi9 & t2shi5); - s[26] = t2slo13 ^ (~t2slo14 & t2slo10); - s[27] = t2shi13 ^ (~t2shi14 & t2shi10); - s[36] = t2slo18 ^ (~t2slo19 & t2slo15); - s[37] = t2shi18 ^ (~t2shi19 & t2shi15); - s[46] = t2slo23 ^ (~t2slo24 & t2slo20); - s[47] = t2shi23 ^ (~t2shi24 & t2shi20); - s[8] = t2slo4 ^ (~t2slo0 & t2slo1); - s[9] = t2shi4 ^ (~t2shi0 & t2shi1); - s[18] = t2slo9 ^ (~t2slo5 & t2slo6); - s[19] = t2shi9 ^ (~t2shi5 & t2shi6); - s[28] = t2slo14 ^ (~t2slo10 & t2slo11); - s[29] = t2shi14 ^ (~t2shi10 & t2shi11); - s[38] = t2slo19 ^ (~t2slo15 & t2slo16); - s[39] = t2shi19 ^ (~t2shi15 & t2shi16); - s[48] = t2slo24 ^ (~t2slo20 & t2slo21); - s[49] = t2shi24 ^ (~t2shi20 & t2shi21); - - // iota - s[0] ^= P1600_ROUND_CONSTANTS[round * 2]; - s[1] ^= P1600_ROUND_CONSTANTS[round * 2 + 1]; - } - }, -}; - -function Keccak() { - // much faster than `new Array(50)` - this.state = [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]; - - this.blockSize = null; - this.count = 0; - this.squeezing = false; -} - -Keccak.prototype.initialize = function (rate) { - for (let i = 0; i < 50; ++i) this.state[i] = 0; - this.blockSize = rate / 8; - this.count = 0; - this.squeezing = false; -}; - -Keccak.prototype.absorb = function (data) { - for (let i = 0; i < data.length; ++i) { - this.state[~~(this.count / 4)] ^= data[i] << (8 * (this.count % 4)); - this.count += 1; - if (this.count === this.blockSize) { - keccakState.p1600(this.state); - this.count = 0; - } - } -}; - -Keccak.prototype.absorbLastFewBits = function (bits) { - this.state[~~(this.count / 4)] ^= bits << (8 * (this.count % 4)); - if ((bits & 0x80) !== 0 && this.count === this.blockSize - 1) { - keccakState.p1600(this.state); - } - this.state[~~((this.blockSize - 1) / 4)] - ^= 0x80 << (8 * ((this.blockSize - 1) % 4)); - keccakState.p1600(this.state); - this.count = 0; - this.squeezing = true; -}; - -Keccak.prototype.squeeze = function (length) { - if (!this.squeezing) this.absorbLastFewBits(0x01); - - const output = Buffer.alloc(length); - for (let i = 0; i < length; ++i) { - output[i] = (this.state[~~(this.count / 4)] >>> (8 * (this.count % 4))) & 0xff; - this.count += 1; - if (this.count === this.blockSize) { - keccakState.p1600(this.state); - this.count = 0; - } - } - - return output; -}; - -module.exports = Keccak; diff --git a/test/unit/contract/contractMethod.test.js b/test/unit/contract/contractMethod.test.js index a82969c7..99dea875 100644 --- a/test/unit/contract/contractMethod.test.js +++ b/test/unit/contract/contractMethod.test.js @@ -2,6 +2,8 @@ import ContractMethod from '../../../src/contract/ContractMethod'; import ContractFactory from '../../../src/contract/index'; const stageEndpoint = 'https://explorer-test-tdvw.aelf.io/chain'; import AElf from '../../../src/index'; +import { Transaction } from '../../../src/util/proto'; + describe('contract method', () => { let aelf = new AElf(new AElf.providers.HttpProvider(stageEndpoint)); const chain = aelf.chain; @@ -11,6 +13,7 @@ describe('contract method', () => { }); const factory = new ContractFactory(chain, fds, AElf.wallet); test('constructor', () => { + console.log(factory.services, 'xxx'); const method = factory.services[0].methods['Register'].resolve(); const contractMethod = new ContractMethod( chain, @@ -35,7 +38,7 @@ describe('contract method', () => { expect(contractMethod).toHaveProperty('getSignedTx'); expect(contractMethod).toHaveProperty('getRawTx'); }); - test('pack input', () => { + test('test pack input', () => { const method = factory.services[0].methods['GetAward'].resolve(); const contractMethod = new ContractMethod( chain, @@ -44,34 +47,74 @@ describe('contract method', () => { AElf.wallet ); const result = contractMethod.packInput( - '4046e35079e2f2285347fbc70c3b1d2a6eacd069c521e3704f8cc6faa6fef989' + '0a2005c3b3959caeee55b5db4004f6f9d76860aae818ce7b33d210a446ecb2754682' ); expect(result).toBeInstanceOf(Buffer); expect(result.toString('hex')).toBe( - '0a204046e35079e2f2285347fbc70c3b1d2a6eacd069c521e3704f8cc6faa6fef989' + '0a220a2005c3b3959caeee55b5db4004f6f9d76860aae818ce7b33d210a446ecb2754682' ); expect(contractMethod.packInput()).toEqual(null); }); - test('contract method', async () => { - // aelf = new AElf( - // new AElf.providers.HttpProvider('https://explorer-test.aelf.io/chain') - // ); - const wallet = AElf.wallet.createNewWallet(); - const { GenesisContractAddress } = await aelf.chain.getChainStatus(); - const genesisContract = await aelf.chain.contractAt( - GenesisContractAddress, - wallet + test('test unpack packed input', () => { + const method = factory.services[0].methods['GetAward'].resolve(); + const contractMethod = new ContractMethod( + chain, + method, + address, + AElf.wallet ); - const tokenContractAddress = - await genesisContract.GetContractAddressByName.call( - AElf.utils.sha256('AElf.ContractNames.Token') - ); + const hash = + '0a220a2005c3b3959caeee55b5db4004f6f9d76860aae818ce7b33d210a446ecb2754682'; + expect(contractMethod.unpackPackedInput(hash)).toEqual( + '0a2005c3b3959caeee55b5db4004f6f9d76860aae818ce7b33d210a446ecb2754682' + ); + expect(contractMethod.unpackPackedInput()).toEqual(null); + }); + test('test unpack output', () => { + const method = factory.services[0].methods['GetAward'].resolve(); + const contractMethod = new ContractMethod( + chain, + method, + address, + AElf.wallet + ); + const hash = '088088deee9d92b4888a01'; + const result = contractMethod.unpackOutput(hash); + expect(result).toEqual({ value: '-8498063171937401856' }); + expect(contractMethod.unpackOutput()).toEqual(null); + }); + test('test output', () => { + const method = factory.services[0].methods['GetAward'].resolve(); + const contractMethod = new ContractMethod( + chain, + method, + address, + AElf.wallet + ); + const hash = { + value: '4046e35079e2f2285347fbc70c3b1d2a6eacd069c521e3704f8cc6faa6fef989', + }; + const result = contractMethod.packOutput(hash); + expect(result).toBeInstanceOf(Buffer); + expect(result.toString('hex')).toBe('088088deee9d92b4888a01'); + expect(contractMethod.packOutput()).toEqual(null); + }); - // const tokenContract = await aelf.chain.contractAt( - // tokenContractAddress, - // wallet - // ); + // test('contract method', async () => { + // // aelf = new AElf( + // // new AElf.providers.HttpProvider('https://explorer-test.aelf.io/chain') + // // ); + // const wallet = AElf.wallet.createNewWallet(); + // const { GenesisContractAddress } = await aelf.chain.getChainStatus(); + // const genesisContract = await aelf.chain.contractAt( + // GenesisContractAddress, + // wallet + // ); + // const tokenContractAddress = + // await genesisContract.GetContractAddressByName.call( + // AElf.utils.sha256('AElf.ContractNames.Token') + // ); - console.log(tokenContractAddress); - }); + // console.log(tokenContractAddress); + // }); }); diff --git a/test/unit/util/bloom.test.js b/test/unit/util/bloom.test.js index 3a3d993a..3c940565 100644 --- a/test/unit/util/bloom.test.js +++ b/test/unit/util/bloom.test.js @@ -5,14 +5,14 @@ import { isIndexedInBloom, __RewireAPI__ as BloomModuleRewireAPI, } from '../../../src/util/bloom'; -import { keccak256 } from '../../../src/util/hash'; +import { keccak256 } from '../../../src/util/keccak'; const bloom = 'AAAAAAAAAAAAAAAAAAAAAAAIAAQAAQAAAAABAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAgAEAAAAAAAAAAAAAAAAAAAAAAAAAAABAAIAEAAAAAAAAQAEQAAAACQAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAACAAAAAAAABQAAAAAAAEAAAAAACAA=='; const bloomFilter = '0x08200081a06415012858022200cc48143008908c0000824e5405b41520795989024800380a8d4b198910b422b231086c3a62cc402e2573070306f180446440ad401016c3e30781115844d028c89028008a12240c0a2c184c0425b90d7af0530002f981221aa565809132000818c82805023a132a25150400010530ba0080420a10a137054454021882505080a6b6841082d84151010400ba8100c8802d440d060388084052c1300105a0868410648a40540c0f0460e190400807008914361118000a5202e94445ccc088311050052c8002807205212a090d90ba428030266024a910644b1042011aaae05391cc2094c45226400000380880241282ce4e12518c'; const upperBloomFilter = '0x08200081A06415012858022200CC48143008908C0000824E5405B41520795989024800380A8D4B198910B422B231086C3A62CC402E2573070306F180446440AD401016C3E30781115844D028C89028008A12240C0A2C184C0425B90D7AF0530002F981221AA565809132000818C82805023A132A25150400010530BA0080420A10A137054454021882505080A6B6841082D84151010400BA8100C8802D440D060388084052C1300105A0868410648A40540C0F0460E190400807008914361118000A5202E94445CCC088311050052C8002807205212A090D90BA428030266024A910644B1042011AAAE05391CC2094C45226400000380880241282CE4E12518C'; -describe('test bloom',() => { +describe('test bloom', () => { test('test is in', () => { const buffer = Buffer.from(bloom, 'base64').toString('hex'); expect( @@ -24,24 +24,19 @@ describe('test bloom',() => { expect(isInBloom(buffer, 'Burned')).toBeFalsy(); expect(() => isInBloom(bloom, 'Burned')).toThrow(); }); - test('should return true if value is in bloom passing in hex string',() => { + test('should return true if value is in bloom passing in hex string', () => { const hash = keccak256( '0x58a4884182d9e835597f405e5f258290e46ae7c2' - ).replace('0x',''); - expect( - isInBloom( - bloomFilter, - hash - ) - ).toEqual(true); + ).replace('0x', ''); + expect(isInBloom(bloomFilter, hash)).toEqual(true); expect(isInBloom(upperBloomFilter, hash)).toEqual(true); - }) + }); test('should return false if value is not in bloom', () => { expect( isInBloom(bloomFilter, '0x494bfa3a4576ba6cfe835b0deb78834f0c3e3996') ).toEqual(false); }); - test('should throw error if value is not valid bloom',() => { + test('should throw error if value is not valid bloom', () => { expect(() => isInBloom(null, '0x494bfa3a4576ba6cfe835b0deb78834f0c3e3996') ).toThrow('Invalid Bloom'); @@ -55,11 +50,11 @@ describe('test bloom',() => { ) ).toThrow('Invalid Bloom'); }); - test('code point to int',() => { + test('code point to int', () => { const codePointToInt = BloomModuleRewireAPI.__GetDependency__('codePointToInt'); expect(() => codePointToInt(0)).toThrow('invalid bloom'); - }) + }); test('test is event in', () => { expect(isEventInBloom(bloom, 'Burned')).toBeTruthy(); expect(isEventInBloom(bloom, 'DonationReceived')).toBeTruthy(); diff --git a/test/unit/util/httpProvider.test.js b/test/unit/util/httpProvider.test.js index 6e6069a3..35ae6187 100644 --- a/test/unit/util/httpProvider.test.js +++ b/test/unit/util/httpProvider.test.js @@ -1,6 +1,7 @@ require('isomorphic-fetch'); import HttpProvider from '../../../src/util/httpProvider'; const stageEndpoint = 'https://explorer-test-tdvw.aelf.io/'; +// for test timeout jest.useFakeTimers(); jest.spyOn(global, 'setTimeout'); diff --git a/yarn.lock b/yarn.lock index ae2728c7..c4dfbee5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6778,6 +6778,15 @@ jsprim@^1.2.2: json-schema "0.4.0" verror "1.10.0" +keccak@^3.0.3: + version "3.0.3" + resolved "https://registry.npmmirror.com/keccak/-/keccak-3.0.3.tgz#4bc35ad917be1ef54ff246f904c2bbbf9ac61276" + integrity sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + readable-stream "^3.6.0" + kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -7493,6 +7502,11 @@ nice-try@^1.0.4: resolved "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +node-addon-api@^2.0.0: + version "2.0.2" + resolved "https://registry.npmmirror.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" + integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== + node-fetch@^2.6.1: version "2.6.9" resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" @@ -7500,6 +7514,11 @@ node-fetch@^2.6.1: dependencies: whatwg-url "^5.0.0" +node-gyp-build@^4.2.0: + version "4.6.0" + resolved "https://registry.npmmirror.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" + integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"