From 5a84a71a12c66b90c1e1c8590ad5354c5fab9571 Mon Sep 17 00:00:00 2001 From: Jose Hugo De la cruz Romero Date: Mon, 18 Nov 2019 18:06:34 -0600 Subject: [PATCH] Fix Dockerfiles, run benchmarks in individual images, consolidate results --- README.md | 14 +- evm/evmone/Dockerfile | 6 +- evm/geth/Dockerfile | 19 +- evm/input_data/evmcode/blake2b.hex | 1 + evm/input_data/evmcode/blake2b.sol | 407 +++++++++++++ evm/input_data/evmcode/blake2b_huff.hex | 1 + evm/input_data/evmcode/blake2b_huff.huff | 562 ++++++++++++++++++ evm/input_data/evmcode/blake2b_shift.hex | 1 + evm/input_data/evmcode/blake2b_shift.sol | 423 +++++++++++++ .../evmcode/bn128_mul_weierstrudel.hex | 1 + .../evmcode/bn128_mul_weierstrudel.sol | 45 ++ evm/input_data/evmcode/bn256g2mul.hex | 1 + evm/input_data/evmcode/bn256g2mul.sol | 397 +++++++++++++ evm/input_data/evmcode/mul256.hex | 1 + evm/input_data/evmcode/mul256.sol | 51 ++ evm/input_data/evmcode/sha1.hex | 1 + evm/input_data/evmcode/sha1.sol | 131 ++++ evm/input_data/evmcode/sha1_shift.hex | 1 + evm/input_data/evmcode/sha1_shift.sol | 127 ++++ .../input_vectors/blake2b-inputs.json | 17 + .../input_vectors/blake2b_huff-inputs.json | 17 + .../bn128_mul_weierstrudel-inputs.json | 42 ++ .../input_vectors/bn256g2mul-inputs.json | 7 + .../input_vectors/mul256-inputs.json | 7 + evm/input_data/input_vectors/sha1-inputs.json | 17 + evm/parity/Dockerfile | 8 +- evm/scripts/benchevm.py | 303 ++++------ evm/scripts/run_bench.sh | 27 + 28 files changed, 2435 insertions(+), 200 deletions(-) create mode 100644 evm/input_data/evmcode/blake2b.hex create mode 100644 evm/input_data/evmcode/blake2b.sol create mode 100644 evm/input_data/evmcode/blake2b_huff.hex create mode 100644 evm/input_data/evmcode/blake2b_huff.huff create mode 100644 evm/input_data/evmcode/blake2b_shift.hex create mode 100644 evm/input_data/evmcode/blake2b_shift.sol create mode 100644 evm/input_data/evmcode/bn128_mul_weierstrudel.hex create mode 100644 evm/input_data/evmcode/bn128_mul_weierstrudel.sol create mode 100644 evm/input_data/evmcode/bn256g2mul.hex create mode 100644 evm/input_data/evmcode/bn256g2mul.sol create mode 100644 evm/input_data/evmcode/mul256.hex create mode 100644 evm/input_data/evmcode/mul256.sol create mode 100644 evm/input_data/evmcode/sha1.hex create mode 100644 evm/input_data/evmcode/sha1.sol create mode 100644 evm/input_data/evmcode/sha1_shift.hex create mode 100644 evm/input_data/evmcode/sha1_shift.sol create mode 100644 evm/input_data/input_vectors/blake2b-inputs.json create mode 100644 evm/input_data/input_vectors/blake2b_huff-inputs.json create mode 100644 evm/input_data/input_vectors/bn128_mul_weierstrudel-inputs.json create mode 100644 evm/input_data/input_vectors/bn256g2mul-inputs.json create mode 100644 evm/input_data/input_vectors/mul256-inputs.json create mode 100644 evm/input_data/input_vectors/sha1-inputs.json create mode 100755 evm/scripts/run_bench.sh diff --git a/README.md b/README.md index 72bad37..cd6e8c6 100644 --- a/README.md +++ b/README.md @@ -30,10 +30,18 @@ $ cd ../evmone && docker build . -t evmone-bench $ cd ../cita-vm && docker build . -t cita-vm-bench ``` -Run geth benchmarks +Run benchmarks: ``` $ cd evm/ -$ docker run -v $(pwd)/scripts:/scripts -v $(pwd)/evmraceresults:/evmraceresults -it geth-bench -$ cd /scripts && PYTHONIOENCODING=UTF-8 python3 benchgethprecompiles.py +$ ./scripts/run_bench.py ``` + +The previous command will create a new directory `evmraceresults`, containing the following files: + +- evm_benchmarks.csv - consolidated benchmarks +- evm_benchmarks_evmone.csv - evmone benchmarks +- evm_benchmarks_parity.csv - parity benchmarks +- evm_benchmarks_geth.csv - geth benchmarks +- evm_benchmarks_cita-vm.csv - cita vm benchmarks + diff --git a/evm/evmone/Dockerfile b/evm/evmone/Dockerfile index 272fa79..fcdd7b8 100644 --- a/evm/evmone/Dockerfile +++ b/evm/evmone/Dockerfile @@ -18,6 +18,9 @@ RUN apt-get update \ graphviz git openssh-client \ && rm -rf /var/lib/apt/lists/* +# install python modules needed for benchmarking script +RUN pip3 install durationpy jinja2 pandas + # install evmone WORKDIR /root RUN git clone --recursive --single-branch --branch bench-evm-codes https://github.com/cdetrio/evmone @@ -25,9 +28,6 @@ RUN cd evmone && mkdir build RUN cd evmone/build && cmake .. -DEVMONE_TESTING=ON RUN cd evmone/build && cmake --build . -- -j -# install python modules needed for benchmarking script -RUN pip3 install durationpy jinja2 pandas - WORKDIR / CMD /bin/bash diff --git a/evm/geth/Dockerfile b/evm/geth/Dockerfile index 6fd2af7..4e9fd88 100644 --- a/evm/geth/Dockerfile +++ b/evm/geth/Dockerfile @@ -3,11 +3,13 @@ FROM ubuntu:18.04 # https://github.com/kuralabs/docker-python3-dev/blob/master/Dockerfile # System deps -RUN apt-get update -RUN apt-get install -y software-properties-common git sudo build-essential wget curl nano \ +RUN apt-get update \ + && apt-get install -y software-properties-common git sudo build-essential wget curl nano \ autoconf automake cmake libtool make unzip zlib1g-dev texinfo \ gcc musl-dev +# RUN apt-get install -y libudev-dev + # Install Python stack RUN apt-get update \ && apt-get --yes --no-install-recommends install \ @@ -18,20 +20,23 @@ RUN apt-get update \ graphviz git openssh-client \ && rm -rf /var/lib/apt/lists/* +# install python modules needed for benchmarking script +RUN pip3 install durationpy jinja2 pandas + # Install Go 1.11 RUN add-apt-repository ppa:longsleep/golang-backports && apt-get update && apt-get install -y golang-go # install geth RUN go get -u -v github.com/ethereum/go-ethereum # RUN cd /root/go/src/github.com/ethereum/go-ethereum && git checkout v1.8.23 -RUN cd /root/go/src/github.com/ethereum/go-ethereum && git remote add cdetrio https://github.com/cdetrio/go-ethereum.git -RUN cd /root/go/src/github.com/ethereum/go-ethereum && git fetch cdetrio +RUN cd /root/go/src/github.com/ethereum/go-ethereum && git remote add hugo https://github.com/hugo-dc/go-ethereum.git +RUN cd /root/go/src/github.com/ethereum/go-ethereum && git fetch hugo RUN cd /root/go/src/github.com/ethereum/go-ethereum && git checkout evm-code-bencher RUN ln -s /root/go/src/github.com/ethereum/go-ethereum /go-ethereum -# install python modules needed for benchmarking script -RUN pip3 install durationpy jinja2 pandas - WORKDIR / +RUN mkdir -p /evmraceresults +RUN mkdir /evmrace + CMD /bin/bash diff --git a/evm/input_data/evmcode/blake2b.hex b/evm/input_data/evmcode/blake2b.hex new file mode 100644 index 0000000..f85021d --- /dev/null +++ b/evm/input_data/evmcode/blake2b.hex @@ -0,0 +1 @@ +608060405260043610610045577c010000000000000000000000000000000000000000000000000000000060003504631e092423811461004a578063d299dac0146102d7575b600080fd5b34801561005657600080fd5b5061029e600480360360a081101561006d57600080fd5b81019060208101813564010000000081111561008857600080fd5b82018360208201111561009a57600080fd5b803590602001918460018302840111640100000000831117156100bc57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561010f57600080fd5b82018360208201111561012157600080fd5b8035906020019184600183028401116401000000008311171561014357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561019657600080fd5b8201836020820111156101a857600080fd5b803590602001918460018302840111640100000000831117156101ca57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561021d57600080fd5b82018360208201111561022f57600080fd5b8035906020019184600183028401116401000000008311171561025157600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050903567ffffffffffffffff16915061041d9050565b604051808261010080838360005b838110156102c45781810151838201526020016102ac565b5050505090500191505060405180910390f35b3480156102e357600080fd5b5061029e600480360360608110156102fa57600080fd5b81019060208101813564010000000081111561031557600080fd5b82018360208201111561032757600080fd5b8035906020019184600183028401116401000000008311171561034957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561039c57600080fd5b8201836020820111156103ae57600080fd5b803590602001918460018302840111640100000000831117156103d057600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050903567ffffffffffffffff1691506104719050565b61042561161c565b61042d61163c565b61043561161c565b6104528285896104448a6104ae565b61044d8a6104ae565b61055f565b61045c8289610710565b61046682826107ed565b979650505050505050565b61047961161c565b6104a68484602060405190810160405280600081525060206040519081016040528060008152508661041d565b949350505050565b6104b6611679565b60005b8251811015610522576008818401810151906104e1908290840660010160080260400361091e565b8360088404600281106104f057fe5b60200201511883600884046002811061050557fe5b67ffffffffffffffff9092166020929092020152506001016104b9565b506105348160005b6020020151610932565b67ffffffffffffffff16815261054b81600161052a565b67ffffffffffffffff166020820152919050565b67ffffffffffffffff84161580610580575060408467ffffffffffffffff16115b8061058c575060408351115b1561059657600080fd5b61059e61161c565b506040805161010081018252676a09e667f3bcc908815267bb67ae8584caa73b6020820152673c6ef372fe94f82b9181019190915267a54ff53a5f1d36f1606082015267510e527fade682d16080820152679b05688c2b3e6c1f60a0820152671f83d9abfb41bd6b60c0820152675be0cd19137e217960e082015260005b60088110156106645781816008811061063157fe5b602002015187602001518260088110151561064857fe5b67ffffffffffffffff909216602092909202015260010161061c565b50846106728551600861091e565b60208881018051805167ffffffffffffffff94189490941863010100001883169093528551835160809081018051909218841690915286820151845160a0018051909118841690528551845160c00180519091188416905290850151925160e001805190931882169092528681169188019190915284519060009082161115610707576106ff8786610710565b608060608801525b50505050505050565b60005b81518110156107e857826060015167ffffffffffffffff166080141561077457606083015160408401805167ffffffffffffffff9092169091016fffffffffffffffffffffffffffffffff16905261076c8360006109b4565b600060608401525b60608301805167ffffffffffffffff60018201811690925216610795611694565b50835183516000908590859081106107a957fe5b01602001517f01000000000000000000000000000000000000000000000000000000000000009081900481020490508082840153505050600101610713565b505050565b60608201805160408401805167ffffffffffffffff8084169182016fffffffffffffffffffffffffffffffff169092526001909201169091526000610830611694565b508351825b608081101561084b578281830153600101610835565b506108578560016109b4565b60005b6080860151600890048110156108a657602086015161087e90826008811061052a57fe5b85826008811061088a57fe5b67ffffffffffffffff909216602092909202015260010161085a565b50604085608001511015610917576108ed6108da8660200151600888608001518115156108cf57fe5b046008811061052a57fe5b6080870151600716600802604003611450565b60808601518590600890046008811061090257fe5b67ffffffffffffffff90921660209290920201525b5050505050565b60020a67ffffffffffffffff918216021690565b600067010000000000000060ff8316026501000000000061ff00841602630100000062ff000085160261010063ff000000861681029064ff00000000871604630100000065ff00000000008816046501000000000066ff00000000000089160467010000000000000067ff000000000000008a16041818181818181892915050565b6109bc6116b3565b6109c46116b3565b6109cc61161c565b506040805161010081018252676a09e667f3bcc908815267bb67ae8584caa73b6020820152673c6ef372fe94f82b9181019190915267a54ff53a5f1d36f1606082015267510e527fade682d16080820152679b05688c2b3e6c1f60a0820152671f83d9abfb41bd6b60c0820152675be0cd19137e217960e082015260005b6008811015610ac45760208601518160088110610a6357fe5b6020020151848260108110610a7457fe5b67ffffffffffffffff9092166020929092020152818160088110610a9457fe5b6020020151846008830160108110610aa857fe5b67ffffffffffffffff9092166020929092020152600101610a4a565b506040850180516101808501805167ffffffffffffffff928316188216905290516101a085018051680100000000000000006fffffffffffffffffffffffffffffffff9093169290920490911890911690528315610b31576101c0830180511967ffffffffffffffff1690525b600080805b60108160ff161015610bbe576000925060038116801515610b71578851600460ff84160460ff16600481101515610b6957fe5b602002015192505b67ffffffffffffffff8160030360400260020a8404169350610b9284610932565b8660ff841660108110610ba157fe5b67ffffffffffffffff909216602092909202015250600101610b36565b50610be185600060046008600c89845b60200201518a60015b6020020151611472565b610bfe85600160056009600d8960025b60200201518a6003610bd7565b610c1b8560026006600a600e8960045b60200201518a6005610bd7565b610c388560036007600b600f8960065b60200201518a6007610bd7565b610c558560006005600a600f8960085b60200201518a6009610bd7565b610c728560016006600b600c89600a5b60200201518a600b610bd7565b610c8f85600260076008600d89600c5b60200201518a600d610bd7565b610cab85600360046009600e89815b60200201518a600f610bd7565b610cc885600060046008600c89600e5b60200201518a600a610bd7565b610ce585600160056009600d8960045b60200201518a6008610bd7565b610cf98560026006600a600e896009610c9e565b610d168560036007600b600f89600d5b60200201518a6006610bd7565b610d338560006005600a600f8960015b60200201518a600c610bd7565b610d508560016006600b600c8960005b60200201518a6002610bd7565b610d6485600260076008600d89600b610c2b565b610d7885600360046009600e896005610bf1565b610d8c85600060046008600c89600b610cd8565b610da985600160056009600d89600c5b60200201518a6000610bd7565b610dbd8560026006600a600e896005610d43565b610dd08560036007600b600f8981610c82565b610dec8560006005600a600f89825b60200201518a600e610bd7565b610e008560016006600b600c896003610d09565b610e1385600260076008600d8983610bce565b610e2f85600360046009600e89825b60200201518a6004610bd7565b610e4385600060046008600c896007610c48565b610e5785600160056009600d896003610bce565b610e6b8560026006600a600e89600d610d26565b610e7e8560036007600b600f8982610ddf565b610e928560006005600a600f896002610d09565b610ea68560016006600b600c896005610cbb565b610eba85600260076008600d896004610d9c565b610ece85600360046009600e89600f610cd8565b610ee285600060046008600c896009610d9c565b610ef585600160056009600d8983610c2b565b610f088560026006600a600e8984610e22565b610f1c8560036007600b600f89600a610c9e565b610f308560006005600a600f89600e610bce565b610f438560016006600b600c8982610d26565b610f5785600260076008600d896006610cd8565b610f6a85600360046009600e8984610c82565b610f7e85600060046008600c896002610d26565b610f9285600160056009600d896006610cbb565b610fa68560026006600a600e896000610c65565b610fba8560036007600b600f896008610bf1565b610fce8560006005600a600f896004610c82565b610fe28560016006600b600c896007610c0e565b610ff685600260076008600d89600f610ddf565b61100a85600360046009600e896001610c48565b61101d85600060046008600c8981610c0e565b61103085600160056009600d8984610c9e565b6110438560026006600a600e8981610c82565b6110578560036007600b600f896004610cbb565b61106a8560006005600a600f8984610c2b565b61107d8560016006600b600c8983610bf1565b61109185600260076008600d896009610d43565b6110a585600360046009600e896008610c65565b6110b985600060046008600c89600d610c65565b6110cd85600160056009600d896007610ddf565b6110e18560026006600a600e89600c610bce565b6110f48560036007600b600f8984610c48565b6111078560006005600a600f8983610d9c565b61111b8560016006600b600c89600f610e22565b61112e85600260076008600d8982610d09565b61114285600360046009600e896002610cbb565b61115685600060046008600c896006610c9e565b61116a85600160056009600d89600e610c48565b61117e8560026006600a600e89600b610bf1565b6111928560036007600b600f896000610cd8565b6111a68560006005600a600f89600c610d43565b6111ba8560016006600b600c89600d610c2b565b6111ce85600260076008600d896001610e22565b6111e285600360046009600e89600a610c0e565b6111f685600060046008600c89600a610d43565b61120a85600160056009600d896008610e22565b61121e8560026006600a600e896007610d09565b6112328560036007600b600f896001610c0e565b6112458560006005600a600f8981610c65565b6112598560016006600b600c896009610ddf565b61126d85600260076008600d896003610d26565b61128185600360046009600e89600d610d9c565b61129485600060046008600c8984610bce565b6112a885600160056009600d896002610bf1565b6112bc8560026006600a600e896004610c0e565b6112d08560036007600b600f896006610c2b565b6112e48560006005600a600f896008610c48565b6112f88560016006600b600c89600a610c65565b61130c85600260076008600d89600c610c82565b61131f85600360046009600e8981610c9e565b61133385600060046008600c89600e610cbb565b61134785600160056009600d896004610cd8565b61135b8560026006600a600e896009610c9e565b61136f8560036007600b600f89600d610d09565b6113838560006005600a600f896001610d26565b6113978560016006600b600c896000610d43565b6113ab85600260076008600d89600b610c2b565b6113bf85600360046009600e896005610bf1565b60005b60088160ff161015611446578560ff6008830116601081106113e057fe5b60200201518660ff8316601081106113f457fe5b602002015189602001518360ff1660088110151561140e57fe5b6020020151181888602001518260ff1660088110151561142a57fe5b67ffffffffffffffff90921660209290920201526001016113c2565b5050505050505050565b60008160020a8367ffffffffffffffff1681151561146a57fe5b049392505050565b600087876010811061148057fe5b60200201519050600088876010811061149557fe5b6020020151905060008987601081106114aa57fe5b6020020151905060008a87601081106114bf57fe5b60200201519050680100000000000000008684860108935068010000000000000000640100000000858318096401000000008583180418905068010000000000000000818308915068010000000000000000650100000000008385180963010000008385180418925068010000000000000000858486010893506801000000000000000066010000000000008583180962010000858318041890506801000000000000000081830891506801000000000000000060028385180967800000000000000083851804189250838b8b60108110151561159857fe5b67ffffffffffffffff9092166020929092020152828b8a601081106115b957fe5b67ffffffffffffffff9092166020929092020152818b89601081106115da57fe5b67ffffffffffffffff9092166020929092020152808b88601081106115fb57fe5b67ffffffffffffffff90921660209290920201525050505050505050505050565b610100604051908101604052806008906020820280388339509192915050565b6101e060405190810160405280611651611694565b815260200161165e61161c565b81526000602082018190526040820181905260609091015290565b60408051808201825290600290829080388339509192915050565b6080604051908101604052806004906020820280388339509192915050565b61020060405190810160405280601090602082028038833950919291505056fea165627a7a723058205ce3dcf8a38e14500505928704e477df0d8442659a541a92ee38ff9a90d701910029 \ No newline at end of file diff --git a/evm/input_data/evmcode/blake2b.sol b/evm/input_data/evmcode/blake2b.sol new file mode 100644 index 0000000..36bfbc9 --- /dev/null +++ b/evm/input_data/evmcode/blake2b.sol @@ -0,0 +1,407 @@ +// based on https://github.com/ConsenSys/Project-Alchemy/blob/master/contracts/BLAKE2b/BLAKE2b.sol + +// compiled with solc version:0.5.4+commit.9549d8ff.Emscripten.clang with optimizer enabled + +/* +var definition = `[{"constant":true,"inputs":[{"name":"input","type":"bytes"},{"name":"key","type":"bytes"},{"name":"salt","type":"bytes"},{"name":"personalization","type":"bytes"},{"name":"outlen","type":"uint64"}],"name":"blake2b","outputs":[{"name":"","type":"uint64[8]"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"input","type":"bytes"},{"name":"key","type":"bytes"},{"name":"outlen","type":"uint64"}],"name":"blake2b","outputs":[{"name":"","type":"uint64[8]"}],"payable":false,"stateMutability":"pure","type":"function"}]` +*/ + + +/* +test vectors: https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/blake2b-kat.txt + +input := common.Hex2Bytes("{{input}}") +expected := "{{expected}}" +key := common.Hex2Bytes("") +outlen := uint64(64) +verifyinput, err := abi.Pack("blake2b", input, key, outlen) + +*/ + + +pragma solidity ^0.5.1; + +contract BLAKE2b { + + uint64 constant MASK_0 = 0xFF00000000000000; + uint64 constant MASK_1 = 0x00FF000000000000; + uint64 constant MASK_2 = 0x0000FF0000000000; + uint64 constant MASK_3 = 0x000000FF00000000; + uint64 constant MASK_4 = 0x00000000FF000000; + uint64 constant MASK_5 = 0x0000000000FF0000; + uint64 constant MASK_6 = 0x000000000000FF00; + uint64 constant MASK_7 = 0x00000000000000FF; + + uint64 constant SHIFT_0 = 0x0100000000000000; + uint64 constant SHIFT_1 = 0x0000010000000000; + uint64 constant SHIFT_2 = 0x0000000001000000; + uint64 constant SHIFT_3 = 0x0000000000000100; + + struct BLAKE2b_ctx { + uint256[4] b; //input buffer + uint64[8] h; //chained state + uint128 t; //total bytes + uint64 c; //Size of b + uint outlen; //diigest output size + } + + // Mixing Function + function G(uint64[16] memory v, uint a, uint b, uint c, uint d, uint64 x, uint64 y) private pure { + + // Dereference to decrease memory reads + uint64 va = v[a]; + uint64 vb = v[b]; + uint64 vc = v[c]; + uint64 vd = v[d]; + + //Optimised mixing function + assembly{ + // v[a] := (v[a] + v[b] + x) mod 2**64 + va := addmod(add(va,vb),x, 0x10000000000000000) + //v[d] := (v[d] ^ v[a]) >>> 32 + vd := xor(div(xor(vd,va), 0x100000000), mulmod(xor(vd, va),0x100000000, 0x10000000000000000)) + //v[c] := (v[c] + v[d]) mod 2**64 + vc := addmod(vc,vd, 0x10000000000000000) + //v[b] := (v[b] ^ v[c]) >>> 24 + vb := xor(div(xor(vb,vc), 0x1000000), mulmod(xor(vb, vc),0x10000000000, 0x10000000000000000)) + // v[a] := (v[a] + v[b] + y) mod 2**64 + va := addmod(add(va,vb),y, 0x10000000000000000) + //v[d] := (v[d] ^ v[a]) >>> 16 + vd := xor(div(xor(vd,va), 0x10000), mulmod(xor(vd, va),0x1000000000000, 0x10000000000000000)) + //v[c] := (v[c] + v[d]) mod 2**64 + vc := addmod(vc,vd, 0x10000000000000000) + // v[b] := (v[b] ^ v[c]) >>> 63 + vb := xor(div(xor(vb,vc), 0x8000000000000000), mulmod(xor(vb, vc),0x2, 0x10000000000000000)) + } + + v[a] = va; + v[b] = vb; + v[c] = vc; + v[d] = vd; + } + + + function compress(BLAKE2b_ctx memory ctx, bool last) private pure { + //TODO: Look into storing these as uint256[4] + uint64[16] memory v; + uint64[16] memory m; + + uint64[8] memory IV = [ + 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, + 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, + 0x510e527fade682d1, 0x9b05688c2b3e6c1f, + 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179 + ]; + + + for(uint i=0; i<8; i++){ + v[i] = ctx.h[i]; // v[:8] = h[:8] + v[i+8] = IV[i]; // v[8:] = IV + } + + // + v[12] = v[12] ^ uint64(ctx.t % 2**64); //Lower word of t + v[13] = v[13] ^ uint64(ctx.t / 2**64); + + if(last) v[14] = ~v[14]; //Finalization flag + + uint64 mi; //Temporary stack variable to decrease memory ops + uint b; // Input buffer + + for(uint8 i = 0; i <16; i++){ //Operate 16 words at a time + uint k = i%4; //Current buffer word + mi = 0; + if(k == 0){ + b=ctx.b[i/4]; //Load relevant input into buffer + } + + //Extract relevent input from buffer + assembly{ + mi := and(div(b,exp(2,mul(64,sub(3,k)))), 0xFFFFFFFFFFFFFFFF) + } + + //Flip endianness + m[i] = getWords(mi); + } + + //Mix m + + G( v, 0, 4, 8, 12, m[0], m[1]); + G( v, 1, 5, 9, 13, m[2], m[3]); + G( v, 2, 6, 10, 14, m[4], m[5]); + G( v, 3, 7, 11, 15, m[6], m[7]); + G( v, 0, 5, 10, 15, m[8], m[9]); + G( v, 1, 6, 11, 12, m[10], m[11]); + G( v, 2, 7, 8, 13, m[12], m[13]); + G( v, 3, 4, 9, 14, m[14], m[15]); + + + G( v, 0, 4, 8, 12, m[14], m[10]); + G( v, 1, 5, 9, 13, m[4], m[8]); + G( v, 2, 6, 10, 14, m[9], m[15]); + G( v, 3, 7, 11, 15, m[13], m[6]); + G( v, 0, 5, 10, 15, m[1], m[12]); + G( v, 1, 6, 11, 12, m[0], m[2]); + G( v, 2, 7, 8, 13, m[11], m[7]); + G( v, 3, 4, 9, 14, m[5], m[3]); + + + G( v, 0, 4, 8, 12, m[11], m[8]); + G( v, 1, 5, 9, 13, m[12], m[0]); + G( v, 2, 6, 10, 14, m[5], m[2]); + G( v, 3, 7, 11, 15, m[15], m[13]); + G( v, 0, 5, 10, 15, m[10], m[14]); + G( v, 1, 6, 11, 12, m[3], m[6]); + G( v, 2, 7, 8, 13, m[7], m[1]); + G( v, 3, 4, 9, 14, m[9], m[4]); + + + G( v, 0, 4, 8, 12, m[7], m[9]); + G( v, 1, 5, 9, 13, m[3], m[1]); + G( v, 2, 6, 10, 14, m[13], m[12]); + G( v, 3, 7, 11, 15, m[11], m[14]); + G( v, 0, 5, 10, 15, m[2], m[6]); + G( v, 1, 6, 11, 12, m[5], m[10]); + G( v, 2, 7, 8, 13, m[4], m[0]); + G( v, 3, 4, 9, 14, m[15], m[8]); + + + G( v, 0, 4, 8, 12, m[9], m[0]); + G( v, 1, 5, 9, 13, m[5], m[7]); + G( v, 2, 6, 10, 14, m[2], m[4]); + G( v, 3, 7, 11, 15, m[10], m[15]); + G( v, 0, 5, 10, 15, m[14], m[1]); + G( v, 1, 6, 11, 12, m[11], m[12]); + G( v, 2, 7, 8, 13, m[6], m[8]); + G( v, 3, 4, 9, 14, m[3], m[13]); + + + G( v, 0, 4, 8, 12, m[2], m[12]); + G( v, 1, 5, 9, 13, m[6], m[10]); + G( v, 2, 6, 10, 14, m[0], m[11]); + G( v, 3, 7, 11, 15, m[8], m[3]); + G( v, 0, 5, 10, 15, m[4], m[13]); + G( v, 1, 6, 11, 12, m[7], m[5]); + G( v, 2, 7, 8, 13, m[15], m[14]); + G( v, 3, 4, 9, 14, m[1], m[9]); + + + G( v, 0, 4, 8, 12, m[12], m[5]); + G( v, 1, 5, 9, 13, m[1], m[15]); + G( v, 2, 6, 10, 14, m[14], m[13]); + G( v, 3, 7, 11, 15, m[4], m[10]); + G( v, 0, 5, 10, 15, m[0], m[7]); + G( v, 1, 6, 11, 12, m[6], m[3]); + G( v, 2, 7, 8, 13, m[9], m[2]); + G( v, 3, 4, 9, 14, m[8], m[11]); + + + G( v, 0, 4, 8, 12, m[13], m[11]); + G( v, 1, 5, 9, 13, m[7], m[14]); + G( v, 2, 6, 10, 14, m[12], m[1]); + G( v, 3, 7, 11, 15, m[3], m[9]); + G( v, 0, 5, 10, 15, m[5], m[0]); + G( v, 1, 6, 11, 12, m[15], m[4]); + G( v, 2, 7, 8, 13, m[8], m[6]); + G( v, 3, 4, 9, 14, m[2], m[10]); + + + G( v, 0, 4, 8, 12, m[6], m[15]); + G( v, 1, 5, 9, 13, m[14], m[9]); + G( v, 2, 6, 10, 14, m[11], m[3]); + G( v, 3, 7, 11, 15, m[0], m[8]); + G( v, 0, 5, 10, 15, m[12], m[2]); + G( v, 1, 6, 11, 12, m[13], m[7]); + G( v, 2, 7, 8, 13, m[1], m[4]); + G( v, 3, 4, 9, 14, m[10], m[5]); + + + G( v, 0, 4, 8, 12, m[10], m[2]); + G( v, 1, 5, 9, 13, m[8], m[4]); + G( v, 2, 6, 10, 14, m[7], m[6]); + G( v, 3, 7, 11, 15, m[1], m[5]); + G( v, 0, 5, 10, 15, m[15], m[11]); + G( v, 1, 6, 11, 12, m[9], m[14]); + G( v, 2, 7, 8, 13, m[3], m[12]); + G( v, 3, 4, 9, 14, m[13], m[0]); + + + G( v, 0, 4, 8, 12, m[0], m[1]); + G( v, 1, 5, 9, 13, m[2], m[3]); + G( v, 2, 6, 10, 14, m[4], m[5]); + G( v, 3, 7, 11, 15, m[6], m[7]); + G( v, 0, 5, 10, 15, m[8], m[9]); + G( v, 1, 6, 11, 12, m[10], m[11]); + G( v, 2, 7, 8, 13, m[12], m[13]); + G( v, 3, 4, 9, 14, m[14], m[15]); + + + G( v, 0, 4, 8, 12, m[14], m[10]); + G( v, 1, 5, 9, 13, m[4], m[8]); + G( v, 2, 6, 10, 14, m[9], m[15]); + G( v, 3, 7, 11, 15, m[13], m[6]); + G( v, 0, 5, 10, 15, m[1], m[12]); + G( v, 1, 6, 11, 12, m[0], m[2]); + G( v, 2, 7, 8, 13, m[11], m[7]); + G( v, 3, 4, 9, 14, m[5], m[3]); + + + + //XOR current state with both halves of v + for(uint8 i=0; i<8; ++i){ + ctx.h[i] = ctx.h[i] ^ v[i] ^ v[i+8]; + } + + } + + + function init(BLAKE2b_ctx memory ctx, uint64 outlen, bytes memory key, uint64[2] memory salt, uint64[2] memory person) private pure { + + if(outlen == 0 || outlen > 64 || key.length > 64) revert(); + + uint64[8] memory IV = [ + 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, + 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, + 0x510e527fade682d1, 0x9b05688c2b3e6c1f, + 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179 + ]; + + //Initialize chained-state to IV + for(uint i = 0; i< 8; i++){ + ctx.h[i] = IV[i]; + } + + // Set up parameter block + ctx.h[0] = ctx.h[0] ^ 0x01010000 ^ shift_left(uint64(key.length), 8) ^ outlen; + ctx.h[4] = ctx.h[4] ^ salt[0]; + ctx.h[5] = ctx.h[5] ^ salt[1]; + ctx.h[6] = ctx.h[6] ^ person[0]; + ctx.h[7] = ctx.h[7] ^ person[1]; + + ctx.outlen = outlen; + uint64 i = uint64(key.length); + + //Run hash once with key as input + if(i > 0){ + update(ctx, key); + ctx.c = 128; + } + } + + + function update(BLAKE2b_ctx memory ctx, bytes memory input) private pure { + + for(uint i = 0; i < input.length; i++){ + //If buffer is full, update byte counters and compress + if(ctx.c == 128){ + ctx.t += ctx.c; + compress(ctx, false); + ctx.c = 0; + } + + //Update temporary counter c + uint c = ctx.c++; + + // b -> ctx.b + uint256[4] memory b = ctx.b; + uint8 a = uint8(input[i]); + + // ctx.b[c] = a + assembly{ + mstore8(add(b,c),a) + } + } + } + + + function finalize(BLAKE2b_ctx memory ctx, uint64[8] memory out) private pure { + // Add any uncounted bytes + ctx.t += ctx.c; + + // zero out left over bytes (if key is longer than input) + uint c = ctx.c++; + uint8 a = 0; + uint256[4] memory b = ctx.b; + for(uint i = c; i < 128; i++) { + // ctx.b[i] = 0 + assembly{ + mstore8(add(b,i),a) + } + } + + // Compress with finalization flag + compress(ctx,true); + + //Flip little to big endian and store in output buffer + for(uint i=0; i < ctx.outlen / 8; i++){ + out[i] = getWords(ctx.h[i]); + } + + //Properly pad output if it doesn't fill a full word + if(ctx.outlen < 64){ + out[ctx.outlen/8] = shift_right(getWords(ctx.h[ctx.outlen/8]),64-8*(ctx.outlen%8)); + } + + } + + //Helper function for full hash function + function blake2b(bytes memory input, bytes memory key, bytes memory salt, bytes memory personalization, uint64 outlen) pure public returns(uint64[8] memory){ + + BLAKE2b_ctx memory ctx; + uint64[8] memory out; + + init(ctx, outlen, key, formatInput(salt), formatInput(personalization)); + update(ctx, input); + finalize(ctx, out); + return out; + } + + function blake2b(bytes memory input, bytes memory key, uint64 outlen) pure public returns (uint64[8] memory){ + return blake2b(input, key, "", "", outlen); + } + +// Utility functions + + //Flips endianness of words + function getWords(uint64 a) pure private returns (uint64 b) { + return (a & MASK_0) / SHIFT_0 ^ + (a & MASK_1) / SHIFT_1 ^ + (a & MASK_2) / SHIFT_2 ^ + (a & MASK_3) / SHIFT_3 ^ + (a & MASK_4) * SHIFT_3 ^ + (a & MASK_5) * SHIFT_2 ^ + (a & MASK_6) * SHIFT_1 ^ + (a & MASK_7) * SHIFT_0; + } + + function shift_right(uint64 a, uint shift) pure private returns(uint64 b){ + return uint64(a / 2**shift); + } + + function shift_left(uint64 a, uint shift) pure private returns(uint64){ + return uint64((a * 2**shift) % (2**64)); + } + + //bytes -> uint64[2] + function formatInput(bytes memory input) pure private returns (uint64[2] memory output){ + for(uint i = 0; i +#define macro ROR = takes(2) returns(1) { + mul shr and +} + +// add three uint64 variable pairs +template +#define macro U64_ADD_THREE = takes(3) returns(1) { + // stack state: honestly who has a clue at this point + add add // (a + b + c) + and +} + +// add two uint64 variable pairs +template +#define macro U64_ADD_TWO = takes(2) returns(1) { + // stack state: V? V? V? V? V? V? V? V? V? t x mask mask blah blah blah + add and +} + +// convert a word of 4 big-endian uint64 variables +// to a word of 4 little-endian uint64 variables +#define macro BSWAP_UINT64 = takes(1) returns(0) { + // split word into 8 4-byte chunks and swap the chunks + dup1 OCTO_HI_MASK() and 32 shr swap1 OCTO_LO_MASK() and 32 shl or + // split word into 16 2-byte chunks and swap the chunks + dup1 QUAD_HI_MASK() and 16 shr swap1 QUAD_LO_MASK() and 16 shl or + // split word into 32 1-byte chunks and swap the chunks + dup1 PAIR_HI_MASK() and 8 shr swap1 PAIR_LO_MASK() and 8 shl or +} + +/** + * SLICE_M + * + * Takes 128 bytes of input data, at M0, + * and converts into 16 8-byte variables, each + * stored in indices M0, M1, ..., M15 + * We later combine these into composite 2-variable pairs, + * keeping them separated in memory allows for easy shuffles + **/ +#define macro SLICE_M = takes(0) returns(0) { + // cache the masks because we use them a LOT and we need to reduce code size + MASK_HIHI() MASK_HILO() MASK_LOHI() MASK_LOLO() + // load the data and convert to little endian + M0() mload BSWAP_UINT64() + M1() mload BSWAP_UINT64() + M2() mload BSWAP_UINT64() + M3() mload BSWAP_UINT64() + // stack state: M_15_14_13_12 M_11_10_9_8 M_7_6_5_4 M_3_2_1_0 LOLO LOHI HILO HIHI + dup1 dup9 /*MASK_HIHI()*/ and M12() mstore + dup1 dup8 /*MASK_HILO()*/ and 0x40 shl M13() mstore + dup1 dup7 /*MASK_LOHI()*/ and 0x80 shl M14() mstore + dup5 /*MASK_LOLO()*/ and 0xc0 shl M15() mstore + + dup1 dup8 /*MASK_HIHI()*/ and M8() mstore + dup1 dup7 /*MASK_HILO()*/ and 0x40 shl M9() mstore + dup1 dup6 /*MASK_LOHI()*/ and 0x80 shl M10() mstore + dup4 /*MASK_LOLO()*/ and 0xc0 shl M11() mstore + + dup1 dup7 /*MASK_HIHI()*/ and M4() mstore + dup1 dup6 /*MASK_HILO()*/ and 0x40 shl M5() mstore + dup1 dup5 /*MASK_LOHI()*/ and 0x80 shl M6() mstore + dup3 /*MASK_LOLO()*/ and 0xc0 shl M7() mstore + + dup1 dup6 /*MASK_HIHI()*/ and M0() mstore + dup1 dup5 /*MASK_HILO()*/ and 0x40 shl M1() mstore + dup1 dup4 /*MASK_LOHI()*/ and 0x80 shl M2() mstore + dup2 /*MASK_LOLO()*/ and 0xc0 shl M3() mstore + pop pop pop pop // pop the masks +} + +/** + * MIX_PREAMBLE + * + * Perform two simultaneous mixing steps. + * There are 4 smooshed mixing steps per mix section. + * Each mixing step has a common 'preamble section', but + * the epilogue changes depending on the words we need to cache + **/ +template +#define macro MIX_PREAMBLE = takes(0) returns(4) { + // Va = Va + Vb + X + mload + mload + // I feel I should point out that is not a constant integer, but a dup opcode. + // And yes, we are adding an integer to an templated opcode in this line, intentionally. + // What is not intentional, is that if the integer offset becomes large enough, the dup opcode will compile to a swap opcode. + // I prefer to think of it as less of a bug, and more like the compiler indulging in whimsical opcode polymorphism + dup2 mload mload or U64_ADD_THREE() // Va Vb + // Vd = (Vd xor Va) ror32 + mload dup2 xor ROR() // Vd Va Vb + // Vc = Vc + Vd + mload dup2 U64_ADD_TWO() // Vc Vd Va Vb + // Vb = (Vb xor Vc) ror24 + swap3 dup4 xor ROR() // Vb Vd Va Vc + // Va = Va + Vb + Y + swap2 dup3 mload mload or U64_ADD_THREE() // Va Vd Vb Vc +} + +/** + * MIX_EPILOGUE + * + * This completes a mixing step with the minimum number of swap ops. + * Can only use this in 2/4 steps, in the latter 2 steps we need to store + * our V elements in memory in a very specific order, which adds swap ops + **/ +template +#define macro MIX_EPILOGUE_MINIMUM_SWAPS = takes(0) returns(4) { + dup1 mstore + // Vd = Vd xor Va ror 16 + xor ROR() // Vd Vb Vc + // Vc = Vc + Vd + swap2 dup3 U64_ADD_TWO() // Vc Vb Vd + // Vb = Vb xor Vc ror 63 + dup1 mstore + xor ROR() // Vb Vd +} + +/** + * MIX_EPILOGUE_PRESERVE_V_C + * + * In the 3rd mixing step, we want to write V_12_15 at the position of V_12_13 and V_14_15. + * We then fix up our weird memory layout by writing V_13_14. However this requires Vc to be stored after Vd + **/ +template +#define macro MIX_EPILOGUE_PRESERVE_V_C = takes(0) returns(4) { + dup1 mstore + // Vd = Vd xor Va ror 16 + xor ROR() // Vd Vb Vc + // Vc = Vc + Vd + swap2 dup3 U64_ADD_TWO() // Vc Vb Vd + // Vb = Vb xor Vc ror 63 + swap1 dup2 xor ROR() // Vb Vc Vd +} + +/** + * MIX_EPILOGUE_PRESERVE_V_A_V_C + * + * In the 3rd mixing step, we want to write V_7_4 at the position of V_3_4 and V_7_8. + * We then fix up our weird memory layout by writing V_5_6. However this requires Va to be stored after Vb + **/ +template +#define macro MIX_EPILOGUE_PRESERVE_V_A_V_C = takes(0) returns(4) { + // Vd = Vd xor Va ror 16 + swap1 dup2 xor ROR() // Vd Va Vb Vc + // Vc = Vc + Vd + swap3 dup4 U64_ADD_TWO() // Vc Va Vb Vd + // Vb = Vb xor Vc ror 63 + swap2 dup3 xor ROR() // Vb Va Vc Vd +} + +/** + * MIX_FIRST_SECTION + **/ +template +#define macro MIX_FIRST_SECTION = takes(0) returns(4) { + MIX_PREAMBLE() + MIX_EPILOGUE_MINIMUM_SWAPS() + dup1 mstore + mstore + dup1 mstore + mstore +} + +/** + * MIX_SECOND_SECTION + **/ +template +#define macro MIX_SECOND_SECTION = takes(0) returns(4) { + MIX_PREAMBLE() + MIX_EPILOGUE_MINIMUM_SWAPS() + mstore + mstore +} + +/** + * MIX_THIRD_SECTION + **/ +template +#define macro MIX_THIRD_SECTION = takes(0) returns(4) { + MIX_PREAMBLE() + MIX_EPILOGUE_PRESERVE_V_C() + // Vb Vc Vd + dup3 mstore // V_c_loc will overwrite the word we've erroneously set here + mstore + mstore + mstore +} + +/** + * MIX_FOURTH_SECTION + **/ +template +#define macro MIX_FOURTH_SECTION = takes(0) returns(4) { + MIX_PREAMBLE() + MIX_EPILOGUE_PRESERVE_V_A_V_C() + // Vb Va Vc Vd + dup1 mstore // V_a_loc will overwrite the word we've erroneously set here + mstore + mstore + mstore + mstore +} + +/** + * MIX_SECTION + * + * Perform a round of mixing. There are 16 rounds per compression round + **/ +template +#define macro MIX_SECTION = takes(8) returns(8) { + // We start with 4 cached V-values on the stack, + // followed by variables 't', 'x' and then the cached masks + // stack state: V V V V t x overflow lo hi + + // We can perform two mixes at a time because we store 2 uint64's in a word + // Round 1, 2 + // We want to take V_4_7 and V_15_12, and duplicate V[4], V[12] so that + // V_7_4 and V_15_12 load correct array indices + MIX_FIRST_SECTION() + // Round 3, 4 + MIX_SECOND_SECTION() + + // Round 5, 6 + // We need to take V_15_12 and store V[12] in correct location + MIX_THIRD_SECTION() + + // Round 7, 8 + // We need to take V_7_4 and store V[4] in correct location + MIX_FOURTH_SECTION() +} + +// In COMPRESS, we modify V14 in the final round. Store both +// variants in macros, which we can supply as template parameteres +#define macro DO_V_14_TRANSFORM = takes(0) returns(1) { + V_6_7() dup1 not HI_MASK() and swap1 LO_MASK() and or +} +#define macro NO_V_14_TRANSFORM = takes(0) returns(1) { + V_6_7() +} + +/** + * COMPRESS + * + * Perform a compression round + **/ +template +#define macro COMPRESS = takes(1) returns(0) { + // starting stack: t + // data is already in the hash buffer + // slice it up so that we can easily access 8-byte words + SLICE_M() + // copy V[0,...,8] into V[9,...,15] + // xor t into V_12 + V_4_5() dup2 128 shl xor V_12_13_LOC() mstore + // if this is the final block, negate V_14 + + V_14_15_LOC() mstore + V_2_3() V_10_11_LOC() mstore + V_0_1() V_8_9_LOC() mstore + + // cache V[0,...,8] somewhere else. This way we can used the stored + // values of V as temporaries, to store the hash result H + V_0_1_LOC() mload V_0_1_CACHE() mstore + V_2_3_LOC() mload V_2_3_CACHE() mstore + V_4_5_LOC() mload V_4_5_CACHE() mstore + V_6_7_LOC() mload V_6_7_CACHE() mstore + + // stack state: t x + // *scrambling noises* + MIX_SECTION() + MIX_SECTION() + MIX_SECTION() + MIX_SECTION() + MIX_SECTION() + MIX_SECTION() + MIX_SECTION() + MIX_SECTION() + MIX_SECTION() + MIX_SECTION() + MIX_SECTION() + MIX_SECTION() + + // Xor the old V[0,...,8] with the new ones, plus V[9,...,15] + V_6_7_CACHE() mload V_6_7_LOC() mload xor V_14_15_LOC() mload xor V_6_7_LOC() mstore + V_4_5_CACHE() mload V_4_5_LOC() mload xor V_12_13_LOC() mload xor V_4_5_LOC() mstore + V_2_3_CACHE() mload V_2_3_LOC() mload xor V_10_11_LOC() mload xor V_2_3_LOC() mstore + V_0_1_CACHE() mload V_0_1_LOC() mload xor V_8_9_LOC() mload xor V_0_1_LOC() mstore +} + +// take V[0,...,8] and remove odd zero padding, +// and convert into 64 packed bytes +// (and also convert into big-endian) +#define macro BLAKE2B__PROCESS_OUTPUT = takes(0) returns(0) { + V_0_1_LOC() mload dup1 HI_MASK() and 0x40 shl + swap1 LO_MASK() and 0x80 shl or + V_2_3_LOC() mload dup1 HI_MASK() and 0x40 shr + swap1 LO_MASK() and /* 0x20 shr */ or or BSWAP_UINT64() RESULT_0_LOC() mstore + + V_4_5_LOC() mload dup1 HI_MASK() and 0x40 shl + swap1 LO_MASK() and 0x80 shl or + V_6_7_LOC() mload dup1 HI_MASK() and 0x40 shr + swap1 LO_MASK() and /* 0x20 shr */ or or BSWAP_UINT64() RESULT_1_LOC() mstore +} + +/** + * BLAKE2B__INIT_V + * + * Initialie V + **/ +#define macro BLAKE2B__INIT_V = takes(0) returns(0) { + V_0_1() // load V_0_1 + // we want to XOR the input length with V[0] + // V[0] is located at byte positions [8 - 16] in V_0_1 + // so we need to shift the output length by 16 bytes + 0x00 calldataload 128 shl xor + // we also want V[0] ^ 0x01010000 + 0x0101000000000000000000000000000000000000 xor + V_0_1_LOC() mstore + // store the remainding V indices + V_2_3() V_2_3_LOC() mstore + V_4_5() V_4_5_LOC() mstore + V_6_7() V_6_7_LOC() mstore +} + +/** + * BLAKE2B__MAIN + * + * Entry point to blake2b hash algorithm + **/ +#define macro BLAKE2B__MAIN = takes(0) returns(0) { + // validate that insize <= 64 bytes + 0x00 calldataload 0x41 gt sensible_inputs jumpi + 0x00 0x00 revert + sensible_inputs: + + // cache the most commonly used masks on the stack to reduce code size, + // first attempt was 50kb large and we need to get below 24kb (currently at ~14kb) + ROR_SHIFTS() + ROR_MULTIPLICAND() + OVERFLOW_MASK() + + BLAKE2B__INIT_V() + + // track the total amount of data to hash on the stack + 0x20 calldatasize sub // x + + // place t onto the stack, the amount of buffered data we've hashed/are about to hash + 0x00 + // stack state: t x + + // jump into the condition test in our main loop + blake2b__main_loop_check jump + + blake2b__main_loop: // t y z x + // load data + // we load 0x80 bytes of data + 128 // 128 t x + // 0x20 + t = c = calldata pointer + dup2 0x20 add // c 128 t x + // M0 = start of hash buffer + M0() // M0 c 128 t x + calldatacopy + // update t + 128 add + // if we're here, we're not hashing the final word + COMPRESS() // t x overflow + + // test if we've finished iterating + blake2b__main_loop_check: + // t = amount of bytes hashed + // if t + 128 >= x, we've hit the final round + // so if (t + 128) < x, we keep going + // else, we keep going + // t x + dup2 dup2 128 add lt blake2b__main_loop jumpi + + + // final block + // t = amount of data hashed + // x = amount of data *to* hash + // Step 1: Clear hash buffer. This is so that, if we don't have + // enough data to fill the buffer, we correctly zero-pad the remaining bytes + 0x00 M0() mstore + 0x00 M1() mstore + 0x00 M2() mstore + 0x00 M3() mstore + // we want to copy the remaining data into M0() + // t x + // (x - t) = data to copy + dup1 dup3 sub // (x-t) t x + dup2 0x20 add // calldata pointer + M0() // calldata location + calldatacopy // t x + // t = x, so swap + swap1 + COMPRESS() + + // we're almost done! Remove the weird zero-padding from V + // and convert into big-endian form + BLAKE2B__PROCESS_OUTPUT() + // stack state: t x mask mask mask mask mask mask mask mask + pop pop pop pop pop pop pop pop + // exit, returning the number of bytes requested + 0x00 calldataload RESULT_0_LOC() return +} + +#define macro BLAKE2B__CONSTRUCTOR = takes(0) returns(0) {} \ No newline at end of file diff --git a/evm/input_data/evmcode/blake2b_shift.hex b/evm/input_data/evmcode/blake2b_shift.hex new file mode 100644 index 0000000..b833dd0 --- /dev/null +++ b/evm/input_data/evmcode/blake2b_shift.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b50600436106100365760003560e01c80631e0924231461003b578063d299dac0146102bb575b600080fd5b610282600480360360a081101561005157600080fd5b81019060208101813564010000000081111561006c57600080fd5b82018360208201111561007e57600080fd5b803590602001918460018302840111640100000000831117156100a057600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156100f357600080fd5b82018360208201111561010557600080fd5b8035906020019184600183028401116401000000008311171561012757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561017a57600080fd5b82018360208201111561018c57600080fd5b803590602001918460018302840111640100000000831117156101ae57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561020157600080fd5b82018360208201111561021357600080fd5b8035906020019184600183028401116401000000008311171561023557600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050903567ffffffffffffffff1691506103f49050565b604051808261010080838360005b838110156102a8578181015183820152602001610290565b5050505090500191505060405180910390f35b610282600480360360608110156102d157600080fd5b8101906020810181356401000000008111156102ec57600080fd5b8201836020820111156102fe57600080fd5b8035906020019184600183028401116401000000008311171561032057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561037357600080fd5b82018360208201111561038557600080fd5b803590602001918460018302840111640100000000831117156103a757600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050903567ffffffffffffffff1691506104489050565b6103fc61156d565b61040461158d565b61040c61156d565b61042982858961041b8a610485565b6104248a610485565b610538565b61043382896106dc565b61043d828261079b565b979650505050505050565b61045061156d565b61047d848460206040519081016040528060008152506020604051908101604052806000815250866103f4565b949350505050565b61048d6115ca565b60005b82518110156104fb5760088184018101519067ffffffffffffffff82166007841660010182026040031b9084908404600281106104c957fe5b6020020151188360088404600281106104de57fe5b67ffffffffffffffff909216602092909202015250600101610490565b5061050d8160005b60200201516108cd565b67ffffffffffffffff168152610524816001610503565b67ffffffffffffffff166020820152919050565b67ffffffffffffffff84161580610559575060408467ffffffffffffffff16115b80610565575060408351115b1561056f57600080fd5b61057761156d565b506040805161010081018252676a09e667f3bcc908815267bb67ae8584caa73b6020820152673c6ef372fe94f82b9181019190915267a54ff53a5f1d36f1606082015267510e527fade682d16080820152679b05688c2b3e6c1f60a0820152671f83d9abfb41bd6b60c0820152675be0cd19137e217960e082015260005b600881101561063d5781816008811061060a57fe5b602002015187602001518260088110151561062157fe5b67ffffffffffffffff90921660209290920201526001016105f5565b50835160208781018051805167ffffffffffffffff94851660081b188918630101000018841690528551815160809081018051909218851690915286830151825160a0018051909118851690528551825160c00180519091188516905291850151905160e00180519091188316905286821690880152845190600090821611156106d3576106cb87866106dc565b608060608801525b50505050505050565b60005b815181101561079657826060015167ffffffffffffffff166080141561074057606083015160408401805167ffffffffffffffff9092169091016fffffffffffffffffffffffffffffffff16905261073883600061094f565b600060608401525b60608301805167ffffffffffffffff600182018116909252166107616115e5565b508351835160009085908590811061077557fe5b90602001015160f81c60f81b60f81c905080838301535050506001016106df565b505050565b60608201805160408401805167ffffffffffffffff8084169182016fffffffffffffffffffffffffffffffff1690925260019092011690915260006107de6115e5565b508351825b60808110156107f95782818301536001016107e3565b5061080585600161094f565b60005b60808601516008900481101561085457602086015161082c90826008811061050357fe5b85826008811061083857fe5b67ffffffffffffffff9092166020929092020152600101610808565b506040856080015110156108c65760808501516020860151600860078316810260400392610889929190046008811061050357fe5b67ffffffffffffffff16901c84600887608001518115156108a657fe5b04600881106108b157fe5b67ffffffffffffffff90921660209290920201525b5050505050565b600067010000000000000060ff8316026501000000000061ff00841602630100000062ff000085160261010063ff000000861681029064ff00000000871604630100000065ff00000000008816046501000000000066ff00000000000089160467010000000000000067ff000000000000008a16041818181818181892915050565b610957611604565b61095f611604565b61096761156d565b506040805161010081018252676a09e667f3bcc908815267bb67ae8584caa73b6020820152673c6ef372fe94f82b9181019190915267a54ff53a5f1d36f1606082015267510e527fade682d16080820152679b05688c2b3e6c1f60a0820152671f83d9abfb41bd6b60c0820152675be0cd19137e217960e082015260005b6008811015610a5f57602086015181600881106109fe57fe5b6020020151848260108110610a0f57fe5b67ffffffffffffffff9092166020929092020152818160088110610a2f57fe5b6020020151846008830160108110610a4357fe5b67ffffffffffffffff90921660209290920201526001016109e5565b506040850180516101808501805167ffffffffffffffff928316188216905290516101a085018051680100000000000000006fffffffffffffffffffffffffffffffff9093169290920490911890911690528315610acc576101c0830180511967ffffffffffffffff1690525b600080805b60108160ff161015610b56576000925060038116801515610b0c578851600460ff84160460ff16600481101515610b0457fe5b602002015192505b67ffffffffffffffff83826003036040021c169350610b2a846108cd565b8660ff841660108110610b3957fe5b67ffffffffffffffff909216602092909202015250600101610ad1565b50610b7985600060046008600c89845b60200201518a60015b60200201516113e8565b610b9685600160056009600d8960025b60200201518a6003610b6f565b610bb38560026006600a600e8960045b60200201518a6005610b6f565b610bd08560036007600b600f8960065b60200201518a6007610b6f565b610bed8560006005600a600f8960085b60200201518a6009610b6f565b610c0a8560016006600b600c89600a5b60200201518a600b610b6f565b610c2785600260076008600d89600c5b60200201518a600d610b6f565b610c4385600360046009600e89815b60200201518a600f610b6f565b610c6085600060046008600c89600e5b60200201518a600a610b6f565b610c7d85600160056009600d8960045b60200201518a6008610b6f565b610c918560026006600a600e896009610c36565b610cae8560036007600b600f89600d5b60200201518a6006610b6f565b610ccb8560006005600a600f8960015b60200201518a600c610b6f565b610ce88560016006600b600c8960005b60200201518a6002610b6f565b610cfc85600260076008600d89600b610bc3565b610d1085600360046009600e896005610b89565b610d2485600060046008600c89600b610c70565b610d4185600160056009600d89600c5b60200201518a6000610b6f565b610d558560026006600a600e896005610cdb565b610d688560036007600b600f8981610c1a565b610d848560006005600a600f89825b60200201518a600e610b6f565b610d988560016006600b600c896003610ca1565b610dab85600260076008600d8983610b66565b610dc785600360046009600e89825b60200201518a6004610b6f565b610ddb85600060046008600c896007610be0565b610def85600160056009600d896003610b66565b610e038560026006600a600e89600d610cbe565b610e168560036007600b600f8982610d77565b610e2a8560006005600a600f896002610ca1565b610e3e8560016006600b600c896005610c53565b610e5285600260076008600d896004610d34565b610e6685600360046009600e89600f610c70565b610e7a85600060046008600c896009610d34565b610e8d85600160056009600d8983610bc3565b610ea08560026006600a600e8984610dba565b610eb48560036007600b600f89600a610c36565b610ec88560006005600a600f89600e610b66565b610edb8560016006600b600c8982610cbe565b610eef85600260076008600d896006610c70565b610f0285600360046009600e8984610c1a565b610f1685600060046008600c896002610cbe565b610f2a85600160056009600d896006610c53565b610f3e8560026006600a600e896000610bfd565b610f528560036007600b600f896008610b89565b610f668560006005600a600f896004610c1a565b610f7a8560016006600b600c896007610ba6565b610f8e85600260076008600d89600f610d77565b610fa285600360046009600e896001610be0565b610fb585600060046008600c8981610ba6565b610fc885600160056009600d8984610c36565b610fdb8560026006600a600e8981610c1a565b610fef8560036007600b600f896004610c53565b6110028560006005600a600f8984610bc3565b6110158560016006600b600c8983610b89565b61102985600260076008600d896009610cdb565b61103d85600360046009600e896008610bfd565b61105185600060046008600c89600d610bfd565b61106585600160056009600d896007610d77565b6110798560026006600a600e89600c610b66565b61108c8560036007600b600f8984610be0565b61109f8560006005600a600f8983610d34565b6110b38560016006600b600c89600f610dba565b6110c685600260076008600d8982610ca1565b6110da85600360046009600e896002610c53565b6110ee85600060046008600c896006610c36565b61110285600160056009600d89600e610be0565b6111168560026006600a600e89600b610b89565b61112a8560036007600b600f896000610c70565b61113e8560006005600a600f89600c610cdb565b6111528560016006600b600c89600d610bc3565b61116685600260076008600d896001610dba565b61117a85600360046009600e89600a610ba6565b61118e85600060046008600c89600a610cdb565b6111a285600160056009600d896008610dba565b6111b68560026006600a600e896007610ca1565b6111ca8560036007600b600f896001610ba6565b6111dd8560006005600a600f8981610bfd565b6111f18560016006600b600c896009610d77565b61120585600260076008600d896003610cbe565b61121985600360046009600e89600d610d34565b61122c85600060046008600c8984610b66565b61124085600160056009600d896002610b89565b6112548560026006600a600e896004610ba6565b6112688560036007600b600f896006610bc3565b61127c8560006005600a600f896008610be0565b6112908560016006600b600c89600a610bfd565b6112a485600260076008600d89600c610c1a565b6112b785600360046009600e8981610c36565b6112cb85600060046008600c89600e610c53565b6112df85600160056009600d896004610c70565b6112f38560026006600a600e896009610c36565b6113078560036007600b600f89600d610ca1565b61131b8560006005600a600f896001610cbe565b61132f8560016006600b600c896000610cdb565b61134385600260076008600d89600b610bc3565b61135785600360046009600e896005610b89565b60005b60088160ff1610156113de578560ff60088301166010811061137857fe5b60200201518660ff83166010811061138c57fe5b602002015189602001518360ff166008811015156113a657fe5b6020020151181888602001518260ff166008811015156113c257fe5b67ffffffffffffffff909216602092909202015260010161135a565b5050505050505050565b60008787601081106113f657fe5b60200201519050600088876010811061140b57fe5b60200201519050600089876010811061142057fe5b6020020151905060008a876010811061143557fe5b6020020151905068010000000000000000868486010893508318602081811c91901b67ffffffffffffffff161868010000000000000000818308915067ffffffffffffffff82841860281b1682841860181c18925068010000000000000000858486010893508318601081901c60309190911b67ffffffffffffffff161868010000000000000000818308928318603f81901c60019190911b67ffffffffffffffff1618929150838b8b601081106114e957fe5b67ffffffffffffffff9092166020929092020152828b8a6010811061150a57fe5b67ffffffffffffffff9092166020929092020152818b896010811061152b57fe5b67ffffffffffffffff9092166020929092020152808b886010811061154c57fe5b67ffffffffffffffff90921660209290920201525050505050505050505050565b610100604051908101604052806008906020820280388339509192915050565b6101e0604051908101604052806115a26115e5565b81526020016115af61156d565b81526000602082018190526040820181905260609091015290565b60408051808201825290600290829080388339509192915050565b6080604051908101604052806004906020820280388339509192915050565b61020060405190810160405280601090602082028038833950919291505056fea165627a7a72305820a59dc9d098d29bacdd88cb50c25c96ed4ba3047fd46a5c6ecf57e447a3c699100029 \ No newline at end of file diff --git a/evm/input_data/evmcode/blake2b_shift.sol b/evm/input_data/evmcode/blake2b_shift.sol new file mode 100644 index 0000000..a88c9b7 --- /dev/null +++ b/evm/input_data/evmcode/blake2b_shift.sol @@ -0,0 +1,423 @@ +// based on https://github.com/ConsenSys/Project-Alchemy/blob/master/contracts/BLAKE2b/BLAKE2b.sol + +// compiled with solc version:0.5.4+commit.9549d8ff.Emscripten.clang with optimizer enabled +// hand optimized to replace div and mul with shr and shl + +/* +var definition = `[{"constant":true,"inputs":[{"name":"input","type":"bytes"},{"name":"key","type":"bytes"},{"name":"salt","type":"bytes"},{"name":"personalization","type":"bytes"},{"name":"outlen","type":"uint64"}],"name":"blake2b","outputs":[{"name":"","type":"uint64[8]"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"input","type":"bytes"},{"name":"key","type":"bytes"},{"name":"outlen","type":"uint64"}],"name":"blake2b","outputs":[{"name":"","type":"uint64[8]"}],"payable":false,"stateMutability":"pure","type":"function"}]` +*/ + + +/* +test vectors: https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/blake2b-kat.txt + +input := common.Hex2Bytes("{{input}}") +expected := "{{expected}}" +key := common.Hex2Bytes("") +outlen := uint64(64) +verifyinput, err := abi.Pack("blake2b", input, key, outlen) + +*/ + + + +pragma solidity ^0.5.1; + +contract BLAKE2b { + + uint64 constant MASK_0 = 0xFF00000000000000; + uint64 constant MASK_1 = 0x00FF000000000000; + uint64 constant MASK_2 = 0x0000FF0000000000; + uint64 constant MASK_3 = 0x000000FF00000000; + uint64 constant MASK_4 = 0x00000000FF000000; + uint64 constant MASK_5 = 0x0000000000FF0000; + uint64 constant MASK_6 = 0x000000000000FF00; + uint64 constant MASK_7 = 0x00000000000000FF; + + uint64 constant SHIFT_0 = 0x0100000000000000; + uint64 constant SHIFT_1 = 0x0000010000000000; + uint64 constant SHIFT_2 = 0x0000000001000000; + uint64 constant SHIFT_3 = 0x0000000000000100; + + struct BLAKE2b_ctx { + uint256[4] b; //input buffer + uint64[8] h; //chained state + uint128 t; //total bytes + uint64 c; //Size of b + uint outlen; //diigest output size + } + + // Mixing Function + function G(uint64[16] memory v, uint a, uint b, uint c, uint d, uint64 x, uint64 y) private pure { + + // Dereference to decrease memory reads + uint64 va = v[a]; + uint64 vb = v[b]; + uint64 vc = v[c]; + uint64 vd = v[d]; + + //Optimised mixing function + assembly{ + // v[a] := (v[a] + v[b] + x) mod 2**64 + va := addmod(add(va,vb),x, 0x10000000000000000) + //v[d] := (v[d] ^ v[a]) >>> 32 + //vd := xor(div(xor(vd,va), 0x100000000), mulmod(xor(vd, va),0x100000000, 0x10000000000000000)) + vd := xor( + shr(32, xor(vd,va)), + and(shl(32, xor(vd, va)), 0xffffffffffffffff) + ) + //v[c] := (v[c] + v[d]) mod 2**64 + vc := addmod(vc,vd, 0x10000000000000000) + //v[b] := (v[b] ^ v[c]) >>> 24 + //vb := xor(div(xor(vb,vc), 0x1000000), mulmod(xor(vb, vc),0x10000000000, 0x10000000000000000)) + vb := xor( + shr(24, xor(vb,vc)), + and(shl(40, xor(vb, vc)), 0xffffffffffffffff) + ) + + // v[a] := (v[a] + v[b] + y) mod 2**64 + va := addmod(add(va,vb),y, 0x10000000000000000) + //va := and(add(add(va,vb),y), 0xffffffffffffffff) more gas + //v[d] := (v[d] ^ v[a]) >>> 16 + //vd := xor(div(xor(vd,va), 0x10000), mulmod(xor(vd, va),0x1000000000000, 0x10000000000000000)) + vd := xor( + shr(16, xor(vd,va)), + and(shl(48, xor(vd, va)), 0xffffffffffffffff) + ) + //v[c] := (v[c] + v[d]) mod 2**64 + vc := addmod(vc,vd, 0x10000000000000000) + //vc := and(add(vc,vd), 0xffffffffffffffff) more gas + // v[b] := (v[b] ^ v[c]) >>> 63 + //vb := xor(div(xor(vb,vc), 0x8000000000000000), mulmod(xor(vb, vc),0x2, 0x10000000000000000)) + vb := xor( + shr(63, xor(vb,vc)), + and(shl(1, xor(vb, vc)), 0xffffffffffffffff) + ) + } + + v[a] = va; + v[b] = vb; + v[c] = vc; + v[d] = vd; + } + + + function compress(BLAKE2b_ctx memory ctx, bool last) private pure { + //TODO: Look into storing these as uint256[4] + uint64[16] memory v; + uint64[16] memory m; + + uint64[8] memory IV = [ + 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, + 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, + 0x510e527fade682d1, 0x9b05688c2b3e6c1f, + 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179 + ]; + + + for(uint i=0; i<8; i++){ + v[i] = ctx.h[i]; // v[:8] = h[:8] + v[i+8] = IV[i]; // v[8:] = IV + } + + v[12] = v[12] ^ uint64(ctx.t % 2**64); //Lower word of t + v[13] = v[13] ^ uint64(ctx.t / 2**64); + + if(last) v[14] = ~v[14]; //Finalization flag + + uint64 mi; //Temporary stack variable to decrease memory ops + uint b; // Input buffer + + for(uint8 i = 0; i <16; i++){ //Operate 16 words at a time + uint k = i%4; //Current buffer word + mi = 0; + if(k == 0){ + b=ctx.b[i/4]; //Load relevant input into buffer + } + + //Extract relevent input from buffer + assembly{ + //mi := and(div(b,exp(2,mul(64,sub(3,k)))), 0xFFFFFFFFFFFFFFFF) + mi := and(shr(mul(64,sub(3,k)),b),0xFFFFFFFFFFFFFFFF) + } + + //Flip endianness + m[i] = getWords(mi); + } + + //Mix m + + G( v, 0, 4, 8, 12, m[0], m[1]); + G( v, 1, 5, 9, 13, m[2], m[3]); + G( v, 2, 6, 10, 14, m[4], m[5]); + G( v, 3, 7, 11, 15, m[6], m[7]); + G( v, 0, 5, 10, 15, m[8], m[9]); + G( v, 1, 6, 11, 12, m[10], m[11]); + G( v, 2, 7, 8, 13, m[12], m[13]); + G( v, 3, 4, 9, 14, m[14], m[15]); + + + G( v, 0, 4, 8, 12, m[14], m[10]); + G( v, 1, 5, 9, 13, m[4], m[8]); + G( v, 2, 6, 10, 14, m[9], m[15]); + G( v, 3, 7, 11, 15, m[13], m[6]); + G( v, 0, 5, 10, 15, m[1], m[12]); + G( v, 1, 6, 11, 12, m[0], m[2]); + G( v, 2, 7, 8, 13, m[11], m[7]); + G( v, 3, 4, 9, 14, m[5], m[3]); + + + G( v, 0, 4, 8, 12, m[11], m[8]); + G( v, 1, 5, 9, 13, m[12], m[0]); + G( v, 2, 6, 10, 14, m[5], m[2]); + G( v, 3, 7, 11, 15, m[15], m[13]); + G( v, 0, 5, 10, 15, m[10], m[14]); + G( v, 1, 6, 11, 12, m[3], m[6]); + G( v, 2, 7, 8, 13, m[7], m[1]); + G( v, 3, 4, 9, 14, m[9], m[4]); + + + G( v, 0, 4, 8, 12, m[7], m[9]); + G( v, 1, 5, 9, 13, m[3], m[1]); + G( v, 2, 6, 10, 14, m[13], m[12]); + G( v, 3, 7, 11, 15, m[11], m[14]); + G( v, 0, 5, 10, 15, m[2], m[6]); + G( v, 1, 6, 11, 12, m[5], m[10]); + G( v, 2, 7, 8, 13, m[4], m[0]); + G( v, 3, 4, 9, 14, m[15], m[8]); + + + G( v, 0, 4, 8, 12, m[9], m[0]); + G( v, 1, 5, 9, 13, m[5], m[7]); + G( v, 2, 6, 10, 14, m[2], m[4]); + G( v, 3, 7, 11, 15, m[10], m[15]); + G( v, 0, 5, 10, 15, m[14], m[1]); + G( v, 1, 6, 11, 12, m[11], m[12]); + G( v, 2, 7, 8, 13, m[6], m[8]); + G( v, 3, 4, 9, 14, m[3], m[13]); + + + G( v, 0, 4, 8, 12, m[2], m[12]); + G( v, 1, 5, 9, 13, m[6], m[10]); + G( v, 2, 6, 10, 14, m[0], m[11]); + G( v, 3, 7, 11, 15, m[8], m[3]); + G( v, 0, 5, 10, 15, m[4], m[13]); + G( v, 1, 6, 11, 12, m[7], m[5]); + G( v, 2, 7, 8, 13, m[15], m[14]); + G( v, 3, 4, 9, 14, m[1], m[9]); + + + G( v, 0, 4, 8, 12, m[12], m[5]); + G( v, 1, 5, 9, 13, m[1], m[15]); + G( v, 2, 6, 10, 14, m[14], m[13]); + G( v, 3, 7, 11, 15, m[4], m[10]); + G( v, 0, 5, 10, 15, m[0], m[7]); + G( v, 1, 6, 11, 12, m[6], m[3]); + G( v, 2, 7, 8, 13, m[9], m[2]); + G( v, 3, 4, 9, 14, m[8], m[11]); + + + G( v, 0, 4, 8, 12, m[13], m[11]); + G( v, 1, 5, 9, 13, m[7], m[14]); + G( v, 2, 6, 10, 14, m[12], m[1]); + G( v, 3, 7, 11, 15, m[3], m[9]); + G( v, 0, 5, 10, 15, m[5], m[0]); + G( v, 1, 6, 11, 12, m[15], m[4]); + G( v, 2, 7, 8, 13, m[8], m[6]); + G( v, 3, 4, 9, 14, m[2], m[10]); + + + G( v, 0, 4, 8, 12, m[6], m[15]); + G( v, 1, 5, 9, 13, m[14], m[9]); + G( v, 2, 6, 10, 14, m[11], m[3]); + G( v, 3, 7, 11, 15, m[0], m[8]); + G( v, 0, 5, 10, 15, m[12], m[2]); + G( v, 1, 6, 11, 12, m[13], m[7]); + G( v, 2, 7, 8, 13, m[1], m[4]); + G( v, 3, 4, 9, 14, m[10], m[5]); + + + G( v, 0, 4, 8, 12, m[10], m[2]); + G( v, 1, 5, 9, 13, m[8], m[4]); + G( v, 2, 6, 10, 14, m[7], m[6]); + G( v, 3, 7, 11, 15, m[1], m[5]); + G( v, 0, 5, 10, 15, m[15], m[11]); + G( v, 1, 6, 11, 12, m[9], m[14]); + G( v, 2, 7, 8, 13, m[3], m[12]); + G( v, 3, 4, 9, 14, m[13], m[0]); + + + G( v, 0, 4, 8, 12, m[0], m[1]); + G( v, 1, 5, 9, 13, m[2], m[3]); + G( v, 2, 6, 10, 14, m[4], m[5]); + G( v, 3, 7, 11, 15, m[6], m[7]); + G( v, 0, 5, 10, 15, m[8], m[9]); + G( v, 1, 6, 11, 12, m[10], m[11]); + G( v, 2, 7, 8, 13, m[12], m[13]); + G( v, 3, 4, 9, 14, m[14], m[15]); + + + G( v, 0, 4, 8, 12, m[14], m[10]); + G( v, 1, 5, 9, 13, m[4], m[8]); + G( v, 2, 6, 10, 14, m[9], m[15]); + G( v, 3, 7, 11, 15, m[13], m[6]); + G( v, 0, 5, 10, 15, m[1], m[12]); + G( v, 1, 6, 11, 12, m[0], m[2]); + G( v, 2, 7, 8, 13, m[11], m[7]); + G( v, 3, 4, 9, 14, m[5], m[3]); + + + + //XOR current state with both halves of v + for(uint8 i=0; i<8; ++i){ + ctx.h[i] = ctx.h[i] ^ v[i] ^ v[i+8]; + } + + } + + + function init(BLAKE2b_ctx memory ctx, uint64 outlen, bytes memory key, uint64[2] memory salt, uint64[2] memory person) private pure { + + if(outlen == 0 || outlen > 64 || key.length > 64) revert(); + + uint64[8] memory IV = [ + 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, + 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, + 0x510e527fade682d1, 0x9b05688c2b3e6c1f, + 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179 + ]; + + //Initialize chained-state to IV + for(uint i = 0; i< 8; i++){ + ctx.h[i] = IV[i]; + } + + // Set up parameter block + //ctx.h[0] = ctx.h[0] ^ 0x01010000 ^ shift_left(uint64(key.length), 8) ^ outlen; + ctx.h[0] = ctx.h[0] ^ 0x01010000 ^ (uint64(key.length) << 8) ^ outlen; + ctx.h[4] = ctx.h[4] ^ salt[0]; + ctx.h[5] = ctx.h[5] ^ salt[1]; + ctx.h[6] = ctx.h[6] ^ person[0]; + ctx.h[7] = ctx.h[7] ^ person[1]; + + ctx.outlen = outlen; + uint64 i = uint64(key.length); + + //Run hash once with key as input + if(i > 0){ + update(ctx, key); + ctx.c = 128; + } + } + + + function update(BLAKE2b_ctx memory ctx, bytes memory input) private pure { + + for(uint i = 0; i < input.length; i++){ + //If buffer is full, update byte counters and compress + if(ctx.c == 128){ + ctx.t += ctx.c; + compress(ctx, false); + ctx.c = 0; + } + + //Update temporary counter c + uint c = ctx.c++; + + // b -> ctx.b + uint256[4] memory b = ctx.b; + uint8 a = uint8(input[i]); + + // ctx.b[c] = a + assembly{ + mstore8(add(b,c),a) + } + } + } + + + function finalize(BLAKE2b_ctx memory ctx, uint64[8] memory out) private pure { + // Add any uncounted bytes + ctx.t += ctx.c; + + // zero out left over bytes (if key is longer than input) + uint c = ctx.c++; + uint8 a = 0; + uint256[4] memory b = ctx.b; + for(uint i = c; i < 128; i++) { + // ctx.b[i] = 0 + assembly{ + mstore8(add(b,i),a) + } + } + + // Compress with finalization flag + compress(ctx,true); + + //Flip little to big endian and store in output buffer + for(uint i=0; i < ctx.outlen / 8; i++){ + out[i] = getWords(ctx.h[i]); + } + + //Properly pad output if it doesn't fill a full word + if(ctx.outlen < 64){ + //out[ctx.outlen/8] = shift_right(getWords(ctx.h[ctx.outlen/8]),64-8*(ctx.outlen%8)); + out[ctx.outlen/8] = getWords(ctx.h[ctx.outlen/8]) >> (64-8*(ctx.outlen%8)); + } + + } + + //Helper function for full hash function + function blake2b(bytes memory input, bytes memory key, bytes memory salt, bytes memory personalization, uint64 outlen) pure public returns(uint64[8] memory){ + + BLAKE2b_ctx memory ctx; + uint64[8] memory out; + + init(ctx, outlen, key, formatInput(salt), formatInput(personalization)); + update(ctx, input); + finalize(ctx, out); + return out; + } + + function blake2b(bytes memory input, bytes memory key, uint64 outlen) pure public returns (uint64[8] memory){ + return blake2b(input, key, "", "", outlen); + } + +// Utility functions + + //Flips endianness of words + function getWords(uint64 a) pure private returns (uint64 b) { + return (a & MASK_0) / SHIFT_0 ^ + (a & MASK_1) / SHIFT_1 ^ + (a & MASK_2) / SHIFT_2 ^ + (a & MASK_3) / SHIFT_3 ^ + (a & MASK_4) * SHIFT_3 ^ + (a & MASK_5) * SHIFT_2 ^ + (a & MASK_6) * SHIFT_1 ^ + (a & MASK_7) * SHIFT_0; + } + + //bytes -> uint64[2] + function formatInput(bytes memory input) pure private returns (uint64[2] memory output){ + for(uint i = 0; i result { + result := 0 + if lt(off, count) { + result := mload(add(ptr, off)) + count := sub(count, off) + if lt(count, 32) { + let mask := not(sub(exp(256, sub(32, count)), 1)) + result := and(result, mask) + } + } + } + + for { let i := 0 } lt(i, totallen) { i := add(i, 64) } { + mstore(scratch, readword(data, i, len)) + mstore(add(scratch, 32), readword(data, add(i, 32), len)) + + // If we loaded the last byte, store the terminator byte + switch lt(sub(len, i), 64) + case 1 { mstore8(add(scratch, sub(len, i)), 0x80) } + + // If this is the last block, store the length + switch eq(i, sub(totallen, 64)) + case 1 { mstore(add(scratch, 32), or(mload(add(scratch, 32)), shl(3, len))) } + + // Expand the 16 32-bit words into 80 + for { let j := 64 } lt(j, 128) { j := add(j, 12) } { + let temp := xor(xor(mload(add(scratch, sub(j, 12))), mload(add(scratch, sub(j, 32)))), xor(mload(add(scratch, sub(j, 56))), mload(add(scratch, sub(j, 64))))) + temp := or(and(shl(1, temp), 0xFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE), and(shr(31, temp), 0x0000000100000001000000010000000100000001000000010000000100000001)) + mstore(add(scratch, j), temp) + } + for { let j := 128 } lt(j, 320) { j := add(j, 24) } { + let temp := xor(xor(mload(add(scratch, sub(j, 24))), mload(add(scratch, sub(j, 64)))), xor(mload(add(scratch, sub(j, 112))), mload(add(scratch, sub(j, 128))))) + temp := or(and(shl(2, temp), 0xFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFC), and(shr(30, temp), 0x0000000300000003000000030000000300000003000000030000000300000003)) + mstore(add(scratch, j), temp) + } + + let x := h + let f := 0 + let k := 0 + for { let j := 0 } lt(j, 80) { j := add(j, 1) } { + switch div(j, 20) + case 0 { + // f = d xor (b and (c xor d)) + f := xor(shr(80, x), shr(40, x)) + f := and(shr(120, x), f) + f := xor(shr(40, x), f) + k := 0x5A827999 + } + case 1{ + // f = b xor c xor d + f := xor(shr(120, x), shr(80, x)) + f := xor(shr(40, x), f) + k := 0x6ED9EBA1 + } + case 2 { + // f = (b and c) or (d and (b or c)) + f := or(shr(120, x), shr(80, x)) + f := and(shr(40, x), f) + f := or(and(shr(120, x), shr(80, x)), f) + k := 0x8F1BBCDC + } + case 3 { + // f = b xor c xor d + f := xor(shr(120, x), shr(80, x)) + f := xor(shr(40, x), f) + k := 0xCA62C1D6 + } + // temp = (a leftrotate 5) + f + e + k + w[i] + let temp := and(shr(187, x), 0x1F) + temp := or(and(shr(155, x), 0xFFFFFFE0), temp) + temp := add(f, temp) + temp := add(and(x, 0xFFFFFFFF), temp) + temp := add(k, temp) + temp := add(shr(224, mload(add(scratch, shl(2, j)))), temp) + //x := or(div(x, 0x10000000000), mul(temp, 0x10000000000000000000000000000000000000000)) + x := or(shr(40, x), shl(160, temp)) + x := or(and(x, 0xFFFFFFFF00FFFFFFFF000000000000FFFFFFFF00FFFFFFFF), shl(80, or(and(shr(50, x), 0xC0000000), and(shr(82, x), 0x3FFFFFFF)))) + } + + h := and(add(h, x), 0xFFFFFFFF00FFFFFFFF00FFFFFFFF00FFFFFFFF00FFFFFFFF) + } + ret := shl(96, or(or(or(or(and(shr(32, h), 0xFFFFFFFF00000000000000000000000000000000), and(shr(24, h), 0xFFFFFFFF000000000000000000000000)), and(shr(16, h), 0xFFFFFFFF0000000000000000)), and(shr(8, h), 0xFFFFFFFF00000000)), and(h, 0xFFFFFFFF))) + } + + } +} + diff --git a/evm/input_data/evmcode/sha1_shift.hex b/evm/input_data/evmcode/sha1_shift.hex new file mode 100644 index 0000000..9085c6e --- /dev/null +++ b/evm/input_data/evmcode/sha1_shift.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b506004361061002b5760003560e01c80631605782b14610030575b600080fd5b6100d66004803603602081101561004657600080fd5b81019060208101813564010000000081111561006157600080fd5b82018360208201111561007357600080fd5b8035906020019184600183028401116401000000008311171561009557600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506100f8945050505050565b604080516bffffffffffffffffffffffff199092168252519081900360200190f35b60006040518251602084019350604067ffffffffffffffc06001830116016009828203106001811461012957610130565b6040820191505b50776745230100efcdab890098badcfe001032547600c3d2e1f0610183565b60008383101561017c5750808201519282900392602084101561017c5760001960208590036101000a0119165b9392505050565b60005b8281101561045c5761019984828961014f565b85526101a984602083018961014f565b6020860152604081850310600181146101c1576101ca565b60808286038701535b50604083038114600181146101de576101ee565b8460031b60208701511760208701525b5060405b608081101561027157858101603f19810151603719820151601f19830151600b1984015118911818600181901b7ffffffffefffffffefffffffefffffffefffffffefffffffefffffffefffffffe16601f9190911c7c010000000100000001000000010000000100000001000000010000000116179052600c016101f2565b5060805b6101408110156102f557858101607f19810151606f19820151603f1983015160171984015118911818600281901b7ffffffffcfffffffcfffffffcfffffffcfffffffcfffffffcfffffffcfffffffc16601e9190911c7c030000000300000003000000030000000300000003000000030000000316179052601801610275565b508160008060005b60508110156104325760148104801561032d576001811461034e576002811461036d5760038114610391576103ac565b602885901c605086901c8118607887901c16189350635a82799992506103ac565b8460501c8560781c189350838560281c189350636ed9eba192506103ac565b605085901c607886901c818117602888901c169116179350638f1bbcdc92506103ac565b8460501c8560781c189350838560281c18935063ca62c1d692505b50601f8460bb1c168063ffffffe086609b1c1617905080840190508063ffffffff86160190508083019050808260021b8b015160e01c0190508060a01b8560281c179450633fffffff8560521c1663c00000008660321c161760501b77ffffffff00ffffffff000000000000ffffffff00ffffffff8616179450506001810190506102fd565b5050509190910177ffffffff00ffffffff00ffffffff00ffffffff00ffffffff1690604001610186565b5063ffffffff811667ffffffff000000008260081c166bffffffff00000000000000008360101c166fffffffff0000000000000000000000008460181c1673ffffffff000000000000000000000000000000008560201c161717171760601b94505050505091905056fea165627a7a72305820227af8b272b9b0e3d345f580ebcde55f50e3e8b7ecafabffcadb92e55e4de68e0029 \ No newline at end of file diff --git a/evm/input_data/evmcode/sha1_shift.sol b/evm/input_data/evmcode/sha1_shift.sol new file mode 100644 index 0000000..80b5bca --- /dev/null +++ b/evm/input_data/evmcode/sha1_shift.sol @@ -0,0 +1,127 @@ + +// derived from https://github.com/ensdomains/solsha1/blob/master/contracts/SHA1.sol +// compiled with solc version:0.5.4+commit.9549d8ff.Emscripten.clang with optimizer enabled +// hand optimized to replace div and mul with shr and shl + +/* + var definition = `[{"constant":true,"inputs":[{"name":"data","type":"bytes"}],"name":"sha1","outputs":[{"name":"ret","type":"bytes20"}],"payable":false,"stateMutability":"pure","type":"function"}]`; + + // sha1 test vectors from https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/secure-hashing#shavs + // FIPS 180-4 "SHA Test Vectors for Hashing Byte-Oriented Messages" + + input := common.Hex2Bytes("{{input}}") + // contract returns padded bytes "a94d7bf363f32a5a5b6e9f71b2edaa3f2ae31a61000000000000000000000000" + expected := "{{expected}}000000000000000000000000" + + calldata, err := abi.Pack("sha1", input) +*/ + + + +pragma solidity ^0.5.1; + +contract SHA1 { + + function sha1(bytes memory data) public pure returns(bytes20 ret) { + assembly { + // Get a safe scratch location + let scratch := mload(0x40) + + // Get the data length, and point data at the first byte + let len := mload(data) + data := add(data, 32) + + // Find the length after padding + let totallen := add(and(add(len, 1), 0xFFFFFFFFFFFFFFC0), 64) + switch lt(sub(totallen, len), 9) + case 1 { totallen := add(totallen, 64) } + + let h := 0x6745230100EFCDAB890098BADCFE001032547600C3D2E1F0 + + function readword(ptr, off, count) -> result { + result := 0 + if lt(off, count) { + result := mload(add(ptr, off)) + count := sub(count, off) + if lt(count, 32) { + let mask := not(sub(exp(256, sub(32, count)), 1)) + result := and(result, mask) + } + } + } + + for { let i := 0 } lt(i, totallen) { i := add(i, 64) } { + mstore(scratch, readword(data, i, len)) + mstore(add(scratch, 32), readword(data, add(i, 32), len)) + + // If we loaded the last byte, store the terminator byte + switch lt(sub(len, i), 64) + case 1 { mstore8(add(scratch, sub(len, i)), 0x80) } + + // If this is the last block, store the length + switch eq(i, sub(totallen, 64)) + case 1 { mstore(add(scratch, 32), or(mload(add(scratch, 32)), shl(3, len))) } + + // Expand the 16 32-bit words into 80 + for { let j := 64 } lt(j, 128) { j := add(j, 12) } { + let temp := xor(xor(mload(add(scratch, sub(j, 12))), mload(add(scratch, sub(j, 32)))), xor(mload(add(scratch, sub(j, 56))), mload(add(scratch, sub(j, 64))))) + temp := or(and(shl(1, temp), 0xFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE), and(shr(31, temp), 0x0000000100000001000000010000000100000001000000010000000100000001)) + mstore(add(scratch, j), temp) + } + for { let j := 128 } lt(j, 320) { j := add(j, 24) } { + let temp := xor(xor(mload(add(scratch, sub(j, 24))), mload(add(scratch, sub(j, 64)))), xor(mload(add(scratch, sub(j, 112))), mload(add(scratch, sub(j, 128))))) + temp := or(and(shl(2, temp), 0xFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFCFFFFFFFC), and(shr(30, temp), 0x0000000300000003000000030000000300000003000000030000000300000003)) + mstore(add(scratch, j), temp) + } + + let x := h + let f := 0 + let k := 0 + for { let j := 0 } lt(j, 80) { j := add(j, 1) } { + switch div(j, 20) + case 0 { + // f = d xor (b and (c xor d)) + f := xor(shr(80, x), shr(40, x)) + f := and(shr(120, x), f) + f := xor(shr(40, x), f) + k := 0x5A827999 + } + case 1{ + // f = b xor c xor d + f := xor(shr(120, x), shr(80, x)) + f := xor(shr(40, x), f) + k := 0x6ED9EBA1 + } + case 2 { + // f = (b and c) or (d and (b or c)) + f := or(shr(120, x), shr(80, x)) + f := and(shr(40, x), f) + f := or(and(shr(120, x), shr(80, x)), f) + k := 0x8F1BBCDC + } + case 3 { + // f = b xor c xor d + f := xor(shr(120, x), shr(80, x)) + f := xor(shr(40, x), f) + k := 0xCA62C1D6 + } + // temp = (a leftrotate 5) + f + e + k + w[i] + let temp := and(shr(187, x), 0x1F) + temp := or(and(shr(155, x), 0xFFFFFFE0), temp) + temp := add(f, temp) + temp := add(and(x, 0xFFFFFFFF), temp) + temp := add(k, temp) + temp := add(shr(224, mload(add(scratch, shl(2, j)))), temp) + //x := or(div(x, 0x10000000000), mul(temp, 0x10000000000000000000000000000000000000000)) + x := or(shr(40, x), shl(160, temp)) + x := or(and(x, 0xFFFFFFFF00FFFFFFFF000000000000FFFFFFFF00FFFFFFFF), shl(80, or(and(shr(50, x), 0xC0000000), and(shr(82, x), 0x3FFFFFFF)))) + } + + h := and(add(h, x), 0xFFFFFFFF00FFFFFFFF00FFFFFFFF00FFFFFFFF00FFFFFFFF) + } + ret := shl(96, or(or(or(or(and(shr(32, h), 0xFFFFFFFF00000000000000000000000000000000), and(shr(24, h), 0xFFFFFFFF000000000000000000000000)), and(shr(16, h), 0xFFFFFFFF0000000000000000)), and(shr(8, h), 0xFFFFFFFF00000000)), and(h, 0xFFFFFFFF))) + } + + } +} + diff --git a/evm/input_data/input_vectors/blake2b-inputs.json b/evm/input_data/input_vectors/blake2b-inputs.json new file mode 100644 index 0000000..94cfc26 --- /dev/null +++ b/evm/input_data/input_vectors/blake2b-inputs.json @@ -0,0 +1,17 @@ +[ + { + "name": "blake2b-8415-bytes", + "input": "d299dac000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000002160000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000020df000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000000000000000000000000000000000000000000000000000000000000000000", + "expected": "00000000000000000000000000000000000000000000000063ab78cbe0ab26730000000000000000000000000000000000000000000000007a3ed6e98dd685270000000000000000000000000000000000000000000000008c0ed623514b7377000000000000000000000000000000000000000000000000a1dd7121acce46f60000000000000000000000000000000000000000000000007e4887408a725aa2000000000000000000000000000000000000000000000000245c95d5d6f9a7d80000000000000000000000000000000000000000000000002d804dd90f7a8ff7000000000000000000000000000000000000000000000000edda4612b40f8448" + }, + { + "name": "blake2b-5610-bytes", + "input": "d299dac000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000001680000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000015ea000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "expected": "00000000000000000000000000000000000000000000000025feaa9cff81c3d7000000000000000000000000000000000000000000000000235710a9dc2a572a000000000000000000000000000000000000000000000000db7f0dadcf75dc070000000000000000000000000000000000000000000000002c3703ab8490028f0000000000000000000000000000000000000000000000006b3e37c89238236c000000000000000000000000000000000000000000000000f7ec1ebb5bcfce820000000000000000000000000000000000000000000000007105be946a72072f00000000000000000000000000000000000000000000000059d032c49e6a92f0" + }, + { + "name": "blake2b-2805-bytes", + "input": "d299dac000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000b8000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000af5000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe00000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "expected": "00000000000000000000000000000000000000000000000057eba72ebe7e5cac00000000000000000000000000000000000000000000000065a4ba493abd362900000000000000000000000000000000000000000000000026a1e008fa866e5d000000000000000000000000000000000000000000000000e9e2308cf5e1c8090000000000000000000000000000000000000000000000006e92be25a14ea59c000000000000000000000000000000000000000000000000d1841d8a04dc5fb3000000000000000000000000000000000000000000000000785bd18b9cfdaca5000000000000000000000000000000000000000000000000263db5cfe2f02680" + } +] \ No newline at end of file diff --git a/evm/input_data/input_vectors/blake2b_huff-inputs.json b/evm/input_data/input_vectors/blake2b_huff-inputs.json new file mode 100644 index 0000000..d1adfb7 --- /dev/null +++ b/evm/input_data/input_vectors/blake2b_huff-inputs.json @@ -0,0 +1,17 @@ +[ + { + "name": "blake2b_huff-8415-bytes", + "input": "0000000000000000000000000000000000000000000000000000000000000040000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe", + "expected": "63ab78cbe0ab26737a3ed6e98dd685278c0ed623514b7377a1dd7121acce46f67e4887408a725aa2245c95d5d6f9a7d82d804dd90f7a8ff7edda4612b40f8448" + }, + { + "name": "blake2b_huff-5610-bytes", + "input": "0000000000000000000000000000000000000000000000000000000000000040000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe", + "expected": "25feaa9cff81c3d7235710a9dc2a572adb7f0dadcf75dc072c3703ab8490028f6b3e37c89238236cf7ec1ebb5bcfce827105be946a72072f59d032c49e6a92f0" + }, + { + "name": "blake2b_huff-2805-bytes", + "input": "0000000000000000000000000000000000000000000000000000000000000040000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfe", + "expected": "57eba72ebe7e5cac65a4ba493abd362926a1e008fa866e5de9e2308cf5e1c8096e92be25a14ea59cd1841d8a04dc5fb3785bd18b9cfdaca5263db5cfe2f02680" + } +] \ No newline at end of file diff --git a/evm/input_data/input_vectors/bn128_mul_weierstrudel-inputs.json b/evm/input_data/input_vectors/bn128_mul_weierstrudel-inputs.json new file mode 100644 index 0000000..f458bcd --- /dev/null +++ b/evm/input_data/input_vectors/bn128_mul_weierstrudel-inputs.json @@ -0,0 +1,42 @@ +[ + { + "name": "bn128_mul_weierstrudel-cdetrio2", + "input": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f630644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000", + "expected": "0fd77bc20ccc92d0b4ffacb61e424d6b6fd72a6d151d8b509219520cc1864bb5288d1f482955e8c54e25edd0b042165f5956080040012c123f212f4f3ae89af53006aa526e2b86b15d1dee9c860a14ae854c204a849c93ba61b05837bf52bbd9" + }, + { + "name": "bn128_mul_weierstrudel-chfast1", + "input": "2bd3e6d0f3b142924f5ca7b49ce5b9d54c4703d7ae5648e61d02268b1a0a9fb721611ce0a6af85915e2f1d70300909ce2e49dfad4a4619c8390cae66cefdb20400000000000000000000000000000000000000000000000011138ce750fa15c2", + "expected": "0bf7bceb8008937f680acf513b071028920555ec741a23c7a1ce94012f480e7e25fe6f425ede8643777d99a16875d2edba1f6af0deedfc87adaa94a88223c16028a6344a52a5a9006001bb0ac953540b251334d4aae7c815e84bda7ad1586c31" + }, + { + "name": "bn128_mul_weierstrudel-chfast2", + "input": "070a8d6a982153cae4be29d434e8faef8a47b274a053f5a4ee2a6c9c13c31e5c031b8ce914eba3a9ffb989f9cdd5b0f01943074bf4f0f315690ec3cec6981afc30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46", + "expected": "2991087fdb407821505a609daef81e7d239d790f56920a737ec29f738028aaa11ff2f37464ad918f0333c99ca9d890de452c4486b4b925c808378b8c320d4c1c10bd0b249179a59d7201a7408e6931de0e1687bd016e68b6aa78ec7f5bbfc8ba" + }, + { + "name": "bn128_mul_weierstrudel-chfast3", + "input": "025a6f4181d2b4ea8b724290ffb40156eb0adb514c688556eb79cdea0752c2bb2eff3f31dea215f1eb86023a133a996eb6300b44da664d64251d05381bb8a02e183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e10460b6c3e7ea3", + "expected": "1d0afc9bb1059a0aed80b1e494b673e195cc81c9f61d27c2be1b4d2e219d85e410777acd638132946872de4d6d25f38bdae622ccd5eba13e8727e77c53b0e0ec2c9dcdd26f57f433e4b379cc52dc328cb8e8fb106d21c9539e0a643719ea00ee" + }, + { + "name": "bn128_mul_weierstrudel-cdetrio6", + "input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "expected": "062f82903b8ff1ea92fd79524b3f74a2f9828d919bd74363e9284df1584c29fa005b670c42ef50487eb89c815ffb4dd7063306efd7b010ce8e969a4e85ed6853065ee72dbfa35c88cc6dc9399c260df4b30e8a653c41db751f2907084ac0cdba" + }, + { + "name": "bn128_mul_weierstrudel-cdetrio7", + "input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000", + "expected": "26c8162046eafa5f18a0356fcb3ffb80ced491ef21c7d27f5585cf7d3ca0e1bb15776559e47782083c416c2d862db615a52532733bdc0ddfce7cb21d77ada21e25902c0c8fb910640a519990e377404b3bc56319ba61c65d3e5c4928f99c418d" + }, + { + "name": "bn128_mul_weierstrudel-cdetrio11", + "input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "expected": "0e9c28772a2a79561257f998c9c31e9b47bb592d54b6936bc00066453f50b27816c1cda062bd6cc07463ba71ff1d299223dd1bb9a6ac5cfe1d57a19c87a229e029a4b5947ed4dca6df8349674078a9b3ea3d06b4373d9d7a50866f3de054285d" + }, + { + "name": "bn128_mul_weierstrudel-cdetrio12", + "input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d9830644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000", + "expected": "15b96faea1d3c641392c406d56c4c2437773189efe5f7ba558f96f5a1ed2abcf27e78562e10de3bf1614ff439e00aecfd4a6c724fc4ef939d06c662d88792f9d2dcb8ebd521d0d7a3db329695e2ba0dd0a7bade2e9fa1200ad7c913c5d0bb0cf" + } +] \ No newline at end of file diff --git a/evm/input_data/input_vectors/bn256g2mul-inputs.json b/evm/input_data/input_vectors/bn256g2mul-inputs.json new file mode 100644 index 0000000..07e397a --- /dev/null +++ b/evm/input_data/input_vectors/bn256g2mul-inputs.json @@ -0,0 +1,7 @@ +[ + { + "name": "bn256g2mul-0xAshish", + "input": "b73ab75d00000000000000000000000000000000000000000000000000000002dddefa191800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c212c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b", + "expected": "23997083c2c4409869ee3546806a544c8c16bc46cc88598c4e1c853eb81d45b01142585a23028cbe57783f890d1a2f6837049fce43c9b3b5e8e14c40a43c617a215a23c8a96e1ca11d52cf6e2d6ada4ed01ee7e09b06dbc7f3315e7e6e73b9190edac9f3a977530e28d4a385e614bcb7a8f9c3c3cb65707c1b90b5ea86174512" + } +] \ No newline at end of file diff --git a/evm/input_data/input_vectors/mul256-inputs.json b/evm/input_data/input_vectors/mul256-inputs.json new file mode 100644 index 0000000..e0e98c3 --- /dev/null +++ b/evm/input_data/input_vectors/mul256-inputs.json @@ -0,0 +1,7 @@ +[ + { + "name": "mul256-gcolvin-drag-race", + "input": "26bceb59802431afcbce1fc194c9eaa417b2fb67dc75a95db0bc7ec6b1c8af11df6a1da9a1f5aac137876480252e5dcac62c354ec0d42b76b0642b6181ed099849ea1d57", + "expected": "80baf8d183a4163e36b5076c8ac089871d90f3c75ee88f4a0204ca9ec2833da9" + } +] \ No newline at end of file diff --git a/evm/input_data/input_vectors/sha1-inputs.json b/evm/input_data/input_vectors/sha1-inputs.json new file mode 100644 index 0000000..933348d --- /dev/null +++ b/evm/input_data/input_vectors/sha1-inputs.json @@ -0,0 +1,17 @@ +[ + { + "name": "sha1-10808-bits", + "input": "1605782b000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000005479f07e6b7ea8b6d2bb301d6ce7019e0f27ad55abbb799e6d47681fe609af63434fb84be4309e63159b3638d0d875e7af11a28d10baa185e8902dee5b09e14621610169511a214be6f3d65a667891eded056e44b913bfee3597caeb19031c21f8da5667409fd3c9cd31aaf28c6c08495f9f7b1d135b173fbacae9b6ae79d28f201841b6213618751ef12e81b1172b526d2c5396adf569e30ea5e4b199f287063da73de6817181d672aecb88730e8dc19c587211e7770a8097b5566c69f1bbffa803b578dfd682566eb72c9750a6a1ff7380714f5e548b80ec75b9577cfbe40405ba42dd9ad9ac7d49c6ac0ec893fa647950bb8f81126f7c837388036175818bcd37509540ff52d3ba49d48f594b19a91435cb52ee4518dbe31b3ce0a5f3372f7517892070cc37c226bd307971306235eaac2b4a04413a1781e9527fc8f9574773b7371f98a4adf1259d3a5daef87683432045d541ab25b7f67a635128fc746c6fb2f4d3272d47c92d667cbc60e7c929e43ec57544f77e45a72ae9d564711116cf774cfbbada77b2a4a552164592dc82145404ba8c9aa6491a9750ad0a0bafdef99099f9b220b05621d664ebbb8e13347a0c9e056729302ad73c22287800c31d948b864dab84a42c3b762fbd314e2fb97bc4fbf68317ae735375f8d83d14dd6b16b47c68159ab59d48011cfb553764799029a8fe5eda63bb15f12f4cc79c613006c7f6f97ec75721de13b73685fe63fd6d871f9d6906025aa52a4ff6b62bf114db228042458f1b72740a78ef41e7a0dd5a79da54201f0cda778dd5567727ff720a50a303187674e79061ec9627a79d61ed8e73a31289e5c3039849fc89350ee01adec99c4601e5f9c9c68ccb95a2dc53ad11461acedb2facdfd638496ac781e793298e7e8cb601316684d3e01a5dcffb0fcefc1b93873ce072c40addaa440ae0f9cd4c3a2b0739171d495c74345cfaf08c03f0363f12a01652ee4c19c65f0c74c5369d5fcf7a0023447071086214efbcb84cbceaf001fba706b1769e2d6d090b7bf1fc4fd892f8ee8296cc1d221a00b80b25ccba74d9a22ae4ca04db6df2832d849bd38ad4c685c14e18c822f2d0f08afb1baa152c1e361a93749141f683fd437570ddb1529939540d92ff9a62de11ae1e9adf9b842419ee995d86726595e9f5d53d5523c08f760f5781dd13e095f689cc2fd7be2b9fe02f4cf16edd19acdbbd1a3de482bd2dde6b9261db000a9d11b6ba471ced70f60b4544bcb4f2a14d44f1bb1f063e86d8d4f174bf93ff2f67f5ad3f7d39b9f2ab0dc9173bf3439adbb83c4e3d34b7dc34fc2944f77251ed6b04e5e23e98943f435a431aeb945054ec98053a34ea9f1bb6b67ba9b600a8c32ae1f93907c41ca543932be63832a96e0476e50582a254d3c286710957b9843f3bff4faa6536a3c3102aec0fce38af4497d7543692f669830d0ea1ea692754bff2cf51cce38ada275d941bde0a20d2873b3bbb5402515da7ea9176d366b49ac403d4c806ef1b2030706133f77885c3944316b2e44d4d91c0efc1784aed0bd6e9d391eaff0472067cfd14bcd295c1f2fa63eab34dd045b65c81012eb7487789afd6a962fba02a0d6b58211f05ee8fd128024a351737c43bd942f2f2bf25823384a16d98a36ead959a1608f2e7ef29febb9297d0c6e05382c5a9f96cb8f0d664e6b861247cac674f77bb4ea12f143adc13b965eed3767e2bb02a97053b26ce8e6480267efe06018b92bc64d211fa3ce9dedb3707d346aea717495e54cc53f5207c9d10009df7e6ea599dedee571d9aa86b7c7db43ced5f85798ab1c3d2f4c4bbad63d061d2fe91dc6ae44c5e54dafea84811cc7c86d72b37356333eae585c7c06578ca1b43869ce21503f2ba91ceb369f33f85b927a07c4cf97747227", + "expected": "37b7277fc606556160f9bc28b06fd55f4424d9cc000000000000000000000000" + }, + { + "name": "sha1-21896-bits", + "input": "1605782b00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000ab154ad09ead61540366364b6f311e3d9e3736c71c31bda3b695cbed40f5554d9ef2ab54d10954d3b5f9e909c01a6e97ae8aaf356a4c6ecc87cf86765be2740e55364d586966f73ab677d0fc97a383783f50848143b91e0ee027d96a0ac7be9fdd487777b276d70d97588490507d0b53c3414d1732f839ef62371b54f825836699a1d02f569952a0db248a71750754bedcb56f73b29a40f28065e2b38e7c70f70ccaedebc04f18a8f45448fc9fc2fe1dde2562233d0fd19cbd4cb602484ce5c5c92c07298a18978a657046ae1b4065f55a29dbb24cd95a529b441bcda0178057315dd2851e863dd9b1011a1281f03ad9d32b228d6c7759c88cf47a72405caf3fe7d8c67ae80899fb697f29a66e62db3fdbb1dd31167a3e4314d6589c838ce0c44f25698781203a83f152fbf63b08d5abd6567229d5529676c5523ca8f438b398f9bc1217745d7de7eb15177e62629882457177f41380f0b800f0ad241ce096325a0576b73c20f2bbb94df29b9f00b267bbab551c6b85bbab7a4a109a68051704f2aa0de3430b3763de5613fa2b53b1d0ab5c900f57e175b573c70d885026a4a556123e28138c9a74dcd60206a1dbf531971dcf494324ad6a9fe00a5a8fb5cd77f6c68e024825ba533746334d9d2a1b2f01675946b7cfd13f513d8d9d51430011573f73ee3b5705a3701f2e3b679e921d7cb1d4a440237f983a381ddd5f5edae5ea05966877911ada19d9595cbbd9d8715b85b7ee56f00729ad5811870459bc8a31915bed8784586b86fd5b2de43c7cef306b7961769606683d162f16dad43362c06b3b09d5714cdc5a039a2b8b66eddb9ddb9fba29860bb87c0abd296d4ebe04190bba3a0c1866a10574acd21bc9b9caf64ea154ea6075aeccae522b1639eae2adfb6ffa75ca446e1bd8e9ce0fd55f31cc4d14ce3385e2bfa169748870161882e1a2c2b7bd0754780fa8f75bf23a4ca4a24f70928f96b16fbcd49aee0573e569769a391e4c601563435d5c184d390097fade2b2e68e3804351684bb840c3c00abf5a598a9e6515c4796e6e9f8b7229804871cb1e5a2cddbf11aced73ac9636eb3e6b9a894d76c3fff464c53e377615f21d92d6ceddb30857700b26acb36bc89f66468296b425ae9a56d8f690dbb56471dcb9b4dc6e16be80ff1b5dc00fa4e37be963883f7ce2440803235923d2a07364287f0ba375d86ee011561969fbe226151a4b31f0024d12edabec8353d6c7e15d632b31d0af7877e94933dfe70293ef0f8b761634eeb699af939d0bcd32ac3cd22f76ddd0556787f1294d17d3de4accafbf7c9b8a8ccf56b26cad38ec80cdc446efca562f12360dbc13fa67ccc9674d9a28b7387d76f7c8ba9995b13e3b9d3640269e31495054879eabd4361e6e89c03359be736a47b06e1cacfefb3eedab0142567b05bbba53741d435309553822e32fb51ae2fd4999c55d19418d6af16793b201e929f29aa351bc9d0f681db0b314d3dd34fd8327044cf050f5ce4f01638c33bb51348a8bd4bef0fb61c8c462cae3c4349529b85a90837b06946457781f493be54bbbe00867fa5ef0e2a1d5b8cace755dc40df94ebf07518c95b610c00b693f1251169f9acdb25b100a99ee3d43336bbb39f0b28df0372855825a1793b85ab1c4d9db25bd867579db62076a7ab4c11bcf8fa89092c4914413e2b6b85d969c386f7e7ffedb12a24fb55170d6cbafd60a2d0d6c0ff7bca4493a2f528f7836ac3784978b978e02c72120816cbfda8500bb365bd18d2748febc2ac0c4198e091933a6bd749c40c752b2bf5a618211e4dfa38df36f949be9fef1786f71c3099e51c14868c1599de0e358e444e5c9fc4fb157866cacb2e02023ada553e2387556e444ec22087bffefe7a831e97ff40416245bd20fff647e7c1b253446abd64bd35f42f461a06fd134de052ab0869cc3e8a704d3860e25d16e341c978025190784115003b02f91dc50351421229020b627c7f71d472f8373670ce861c8e49d42f9b8d0ac861cae5be29b49c7c8233c4563f5b711dbf9e9ff07140d056960cf68a49469216bde01ea3c7f0a9109c62c1c1dbea953ace3d5beced81f04ea302be305526e34da1a3901fe3efaef7fef9c84c59162553273e34d1ec782e2e3c93f6cac6174494927b02d88798f658305ea29fc0c668925307f248760dd11bea2764ffa500fc131ad03d76bad3c85cbbfb176118e2a71dd9025df89428233f3426d278f9c854f3c00a0aa285886b2a2636ee3a69512a1c41963c8a4db16ac2a2f806ddca59945c0c912f04ee9f28ecf979f1d4bcfd39b8142a59a5aa90efccbc05c8d5219a047587ce7443000147c7bd2be6d418cd1c18d8287af2b1aefa830bb6e2080573eb67b827a307c09410e5f9b396e586a91a6618f768186cf1d21216711a1f7ecc9359280582fa3841ca6e357bc9ad0d797dc759ffebc0e342c19f659f3ac2948d42745dd1dbc26ff1bf8af9ea46d4b5258b6525a8ca921d8a0d5381a90898509f41e0e1f174076d8a355fce68d70386968d68035acf3522afff55f1f54d4ab9e8d8c43ccf15723bf575183b5d42e289b2caf87c7dc052fa9bdfce3dedd07fd7514e48f4d188aae01bc7dbc9315018c5628c3b17796690ae34f5e5eef85be0b3c2ed969361945864e372d0fe4dc94e428f195c5cb68998446488c38b7db4155424fbd3a1e60024d034c0216517752b091fbb81d39df111c711e28f9ce6a4c5c35dc12aa4c895b52bf8f7f383f81c5821fcb7d3059465a43c254972aa9af398065787c1266e1bb47d166071e259857c920c58797904aff9ad8706943c01693827f895c0ae425ac8ce7643c009a079406539e59bb75695b7211f611cda83ce4a2d2a3250c5ab199a2700e80b8037c04ca169a56348f0e087a1d5a1320c88e97921d4a799f11122d28f9c9678d08422474e86e1f7b33c5810349110005b78836a0ade3dc2bddc3b170f32972f80f167d97577e27f80a0c4fbe23bf4ab4ebb64c8f02f39f3ae752d11aeaa315918e456ab1d24ed243886edefb3bb965e6eb95439dcb1e6564e42bf6974ecad1e20c7b8654e754d0d62559c95b0f93e3f41db1b65d44b8b1024acbbc769e053a5210155af1052486486759795e0de3476518780f6e3e56f4cb81ce7d2966f6a17a3faf52f6ca3284e2c4ea6964c50bf2c26264d910e68db3093f80d33027f3c9b2c1a6090695033f5dd489340fa382889462148e05fba17e43ca9f392b5f90f5a46c95d781041b28120cb253cf47fb8b43bde3a8bddc46b913b986295b8c62c7c786fb690685fec1a7e3f2332420bb4d68dc7ea3a906e1f5f192c21e712ccdb284a74317f79902be67e0c56c9eac66716c243229481a17a755dccfa2ecbf56386454097ed4bbdb510a89a86aaf697189d64b9a841b743c5fc8fe2b313ec280ebff03baf84e7cfd4be84517a7d6d650e92fb9345ea3a3d491b38d5153d7c4d22fbd4ce43e954accd199b9afce9581a921e0d38c13713784bfbdf0de855834be861775f19c79a3eeb4874dbd296be9dec692410e4cf49db16c30cf2f4020a0ca81a6358fbc4c26b7573977dc52da7d6649ac783765be44df19c47ec00ed1777aa4d201faf88d21db2c48de99d561cad42da7ff93e82edb823ae1963d6bdb5743523341efdbcd53beb61dd8622b8230acd50d2da05ed6b03f52009bf3c1be9eb92c429bbaf08d0ad69720fbb1cfcc7d54e254a8e93436616af1ba068fbafbdc40a5787608b13cd5b7120acf252c90df60d806f7db02de7d999c664c6db2038e7e305d4745b86d32d4e923b928dc8ff55528ac8102453f434fa4adf41a317623d65f59a5fe508eb0b46f2440395a1a4db656addadb65c980f1cce99000000000000000000000000000000", + "expected": "0f5176527280b8e3fa69a6c14ce1f759d6e9c67c000000000000000000000000" + }, + { + "name": "sha1-42488-bits", + "input": "1605782b000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000014bfd2f61e1a3e370e78db7a356cff4e3e0a40800ab936d79b89820131c60eceb2cd979c4f1e691365b36a12a1905ae8689c59c876afaa77c5ecb648b051544a588c47c0471008d15369c781c5ccace0bbf36281cb28d62ee99f3cda8b0854d70b65eb4a4c19a4dba042f8b1e9497c9dffb86295524b4365d1491ca10a1496de92ff8a21a761c49814e80788552f5287fc9262eb5341788243935c84749da2c5b6042c2fa00ff0707600fbf050a5b606792a696b1631fdef0824066a13ca01f63f19d95b7e4cb1cb9035ddd024d3318240277ffde2445b12e8a6213d2dc43ad7f5e89a8d8b3f8d11282cb40f17e24a631732ac8901a11955aabeb6e40bb3d5d29f1976ad0d110eaa0790889772fa8a11c7f3f9f7b972bf1f1816cc47f5be5a4e075476a44de9bcfff507624f7d4278f518116d2f53dcd6d7f8566b4e320d52b3f340a15893f01e76ba39491f7fe39c75d135111a1609e5e713269be10cc945682c85ffb2274dbc781dd045efc2057efabc06eb9e4c2174b6312c65e8c91ab9d77acc989a50291e6ee7715ea78ccea7ed9f2d06a43b4b0bac1a13d04bb2273867a4bd75f957accdbee0c69d3026699eb4435167152db033319581e5f20f19498074ff9db584fd50d2d0770970d8fcebb9701b18d7687873ad6b1fabc52817758ab03b18b81f452f107f2caa50e9b01762ed3220d435ca548864942aad444a42ed2118efe870abf3e2b58c89b8a3aca919844087f2dbce5d2a48886a90adda3a128f3f292fbf5823af393fad914c192945fbea551ba4ae16fcdfa57458a9eee55fc257ce74537447ded4ee1fc12d1e1f4d1bda9336d68f0764f1904feb81aeca3d8109e79f7526e7d94e41e5328ee4149bacb8492bba9cb9cb45f403337d43711595fd7a976d968c076fdf09cab7929096762b7de298fab39aa4779916e4d5624dc7da924683edbdd0fe719273ef5119a640dc3942b8d47d37d6c1187e008b264fdd483493ff53039cc59e89147f493933d47384356150a00ca37b8852178e44819ff16a6628efe5d38a0ff595afa177a5f89767a3dc96a37fd34df17a7206444dd77a3ba747eaebdd166bdeddc7825b6575f0e87272cf0efa2dde5cdd591aaf1a4b8eb03ea46b9d23315b4dd60f136ed91327128b68236ae47ad7d06513f20b4fc4d3cf14879b840ba2874867cf7d376a99e4ead609b93da582df56f9eab7e3560af1a20f38a227fe3396da784ee73f80d1ce7a3b9cba12a50d9ff5812491bc96e5913118fea70e65aa3108f2d57a0c84818ec9a3684d6e4be3bfb5e60aa720771d5b821823d2c2a6d0ffdcbbac5d28dc72ccdff4b69bdb01cbe69e0ee422966179f6a0f5ed4cca2b6da95dbc1bb91bf26c2fc518cecce02f8fbcb9e2fa29a7bcc30b9099a53dae5a49d693dd6ab66b2d375f82f5f807063bf5eb0d4a93e5d9f0c1415bea92cdf79d2b2f8707e07ba2f49a051e757c74d38ec618a22ff97eb7653c410ad2fe222c5bdd5b4020c63147b15ec9a27fa13cd190c9ed8177721bc684fbb2a5382f67d5fb2503c61164ffe3cb4b5215fab18788a9c812b10c47e490b3c83d32036ec27be7cccf22c3020efdaa29497fd0f27c7f42892f3ad4c0029c5b698abb1d035ba5869a665b1de8861db6c055e8e8ad443ec1d6eb25b9249d72e5a740476d365bdb40567179065e8ecc57d81f592a29064d9075ee79a2bddc9bb74a07dfdb4feaa57dca978568ab4e90f5384ed97eb0eb35152ee13e76d1e89e3b1a898a4f952f8ca5bc81862a18eff4f8a98b71cc881b7dbacb6c7d1fa9e903d8df6b50b151531720f5d78434ed997dc8f37e28fcfabdade612363d848d0653f5605839e9cc7dcf573d40886e7273b5cddece06f64efa4d00cde8868dc46715fc66f64ee04bd63ab05b6498c0eea6236f322413a2ccf9e672c22960229835d154b9ed967c1986e29419ecbf12ab594f17b62758e9bce3ffa3baa2d42b4f980f6521e619a67db44f6c3d80024cefb5c22b3380dcb165df21fb7cfbe99032b758976689e047be89079e90c76b5603e2031571d6a7e41016d3e2d2dba83989bb33524f7df245252c9494da6a01182f079a3b38d2c26805af9dc082ea170f9ccb29fea56b588afac57eb4e310cc7aba4d1007501c34278cd307fd55d141f8b210c10330fa18fc857e4b687262d565eedbecdf805b0507edaa9a0113382bdd15b283c9b8d33c850d7d8517510823bf11dab62d91373ef26f5bdd3584c6dfa70bd8f7b9059dcb0cdceab32846a9be726c71f7584c5ae6cf5b0f59ff6f24643cddaaa639de01ce7838ee5e051aedaf6447c935c876690586f9ed94c89efac286d35117b20da74cb36ab10d15957efd7fea09fbe5da0fa4fe911e18f9d7ef016c34f5d28d58364da4b95a48c07e01b0a99c5ace173ff2c9216bc96df8e3ab2ad54abd60308857da336f11986e9f21d1cca6e438c66cba7fd6cf17192f8ad745ab5bd2480565b1f948d3008387be8467cf50cec05a2a10cb050430a604931b58d5b05c1272b6edb5cb2c4c9373a4d27a9ae241ef3b419cb796533b9ce1c81e6d3b918247e145b213a4c320509b19b41315a4644bd179054a720460812def898bc5456c6eb9d8a91dbce0a24165e4d13828de605e859af38c7f5fc9df50d103bb5b16430f623879daf9cafaee3acfd3f4bbd75cb0bd6b1086a6ab9b3db2363504e54a2fb2442dcb5244cb51df83a05f4cb6d881c7e2b5013fd0320124bbe6c66e4b2a57e0c77e478e8629cf9da620204a0129f62d5d4071bfe33a211bd3a85f0175fee42053f59495a52d9baf0d17bbf58412e46a94d4060fc90c23aa6245a8c64b0efdfb50585b6f8b1fde9d1e4ddb5528db7304f139683668f03059d08648c4b6a1cbf8267043251e47bff043892673d3cbca85db36403caa2d70b18530e8039c01769f3d05f5be48ec672fe39544566e2b1275ba95362a750d0a39e90e2f8ce7742578fddf1842ef58fde26537de06e243725af51cf107b3d6267964e7c6667d43000ccfc555bafdd1aa9133389c8c155b13bef6941adb4bd1eefa5f82549948b630e21980542d59a096c5b45f25eff1bb1d2824c458af2546884340a8822e2e14dd8244d9bca3eb0de805507622375dabb721e776548a297d1cdd7121f82c19a72e75b99536249b5fc9da6f433a6d40720930a770b6743fbdd34e58b55d9bf0b54c42df7f69b951e060cb7990169884593cddcc7b25754f50d4205f2c5a849b875f711d5efe69f5d6d660d6235dc010a878b0be5f4996417c48daed4d96ee01658e8bddf99c3d6f8a5221efc4b8edcca7e432e6e4cbdefd8a570569e1bae10c9601178619ec3ba744fd972a3dcf28a09da9eaaad253566bc228283db06d65a364e19d8086956d864cfe49f055497874d4ee6073f08804746be4cbd0825883ae1556a5320840dbf2e97ebfaad3cfe63092dc1daa0713f2feceb2778a1f224216f287b80667958cd464a582be800879bc209ba8b5df9b28f234bbb2d34f74abc1439d5d636a3b8815059a1996249d3900c65289fe40c9ac39e3270713d9f6c49850bf1db1dbdbd79b14860c9887352ee5cb2a49ebf24588b9241dfbb2864f978360167f59801c8250d990e42e70796151794a6fe6bcb6c45c3ec518181e282c6bbdca0bc121a78f1b9ce128bfa810d92d16da835668c566097b48e5ae69288936ad024952882309e3a4a060b2f8a49e62eb040ea3bc1978a821ceeada2ef8b8ce79e6c2747c39f5923af6157126dab9d740ee9734815b0120797eb005373fc119699ffd90c4915d0fa60bcd63fa5c31735dc0a6737e320a5bcb81be984aa6aa01c455820c29d24842300613f03ed20e2089a3c3c77d479a405fff9cf930d57d6dd42fda5273a5bf1320106c80b8e359c50dbf77984441b9b77c1fd392b1734244df568cc86ab1c96abd50627b31381949313b494f9dc96fa86b09eaca9428ff702ef220d8d59f6e2f50ef7c4a727956963d3fc2524e87c5fb75e66908a39ebed8092a1fe97e16b64a21144353404d189379f5680a1f22c298e0ded9b6a47a8664b72610622bbfaaa378e83dff665c68282d83c6dfda436f68f418c13b606760fc820f7bada54251239d93f4b6aa4f4d3da011613a4591d251fbbda9ff9f0b5288b00de831b446b4b0d73cf0e1d6ced0ba1bc8c3812ab5f63c3bf4196a280e67f08a47e0561f73d933700bb7e6b080f887e6cf731e4f56e012fde69ae4c519a41c58e6ea84b072ca95ae29d32f010ecd8d494ff9777c1d9ab989bab3d53cd413f562118f232deb8fbcdabecc22901f57b28c70def67bb12b1b2799eda556e6bb61eff1569b5f852e923bf12829275c9fdff659a90113bc9b1f1fabcfbcdbf8a44949aec7550ee9b1fe1beb71ab8c6dacfdd033e2020be3f2acb817e18293b1d796b66f6ab702bf1fe7c0d42e1088f986f2622511602cd039ac3c06ab6046ba5b2e7f5cc82a02ae813773d3e8bfe3a836a8f458bf833e2b7806f19fb6bcbbba38fbec9e6817d85eded57c1026226524c305cef473d3099bb5a2200b89ffbb5a77e4445dd2e44a783ea923b470a0d61235f33820b6b854c9fa681071ac920e421fd0d1c08ffb21a4aa9bb0e74ea1fd1d955979040f9ae95d4e400bfaa8db7c1938a9d9f026c2248928936ad0498da3ebea1edac906e18efeba1257ce0444cd87cb56a5151fa31dd0c3799b98e8cd90243c2ca39723f50c5444c63d144834c836debf7d560304d22080358966b4c78c71936a1c95ef3e2a08f74405f5fd1336cb7ccca8db594f0d2269af7c6334e45f7af8c08cecf125b2c2d874f798aa48dff1aa6570cda9eb947e85d0beb7f08cd0e672163dc3b1106a29f13e5b26d73d8b4e72721b547c402fdbdc7e96897028a95d0a547543b8681ce6498b78c60c59028adbdbf29758b6a8e177a24b013d1eb089c7637d948d968ea1e84197a1d2040b4eed883dbfc8b5c6395d252649ded8ae0fb1299dddb9008901d74a00deb0a67042b16144f351a5508b96ed6f86dbbc6a9ad08f1c47c210d4ae1d8cfba62fa7f70d2e4f4e5c7dee0f7e2be46ee3bd34aed02d7d44f9322d3951c2f1d021d57069576d38a521d3f8cbbb23f16a860aa74059cfdc5b1b90be7e92cf60c6762d678dca74068f6cdb2c4bea86fbad974d7de9debe92aad7652d6c184bc026cebcf52d0c4d9f55621ef059b25dec7d3f0b1d71070389795338e1cb8c3efb38500c820fc500ed3f2d23adbbbbafab23a5cef1a07ba5a710b791426395b0f84425a477fc9e93d694f572cc3aae8420e7f31d603ee3acd6b62cf8b8fbdcaa9f92740c3abc3e10449ee194b39e33e433104e81d212e621fdb4daf6ab5d0833d86a66cd35174f7e1ea31a10ccaff1d8cce8e081afe52d0b0452e812834fc2548b13236ecfd576e64cecc86e7e359167d3b5d1a5607f5f72d2d87ed5a89ab214a0d6d2776fbd5d4fb5c1113730f7ba9a30c049754ba8255e518ec6c683067f7bfffb9b707f99acc1436920f24cbe1578cb516f7ad92827d868bce56d7a5ad29191caa7e2662f0b45dd2e1b2739524a098caf6b3b72c60ce7ffa90652f660525f3c8a1e558c4720e16b562b5f5f7b00555c2466407f4b7d94ff9e4ffe60dea8ece985284f59ab969fd62a77202601df6521f68812668021e64ee3e8f81e9d7b408101eb5a3522138704f228f5f6ab9140c56ef838912aa1e5d5c0fac89a657464ea4792fd88733fa0def665633742bbee2ed4df3a6614a4997c7dadf73afd3b5f0e9f43c1ba67c4f24c7d57f4518f0878467064a14f05d30b2c61280c682f7739d350262c33c6478537d1252fac571de5f389b0f4b3c4d642cbb5948f8bc1d0fb23a465c85b5873628538f89cb065a53d1f69eabbfa1a544642c118080a7cf0ace5e1251d9be4ed9020fbf8c4c6804688b1563b7f8bcff5207acddd004f287c54015091b159346017ee624c2e546fa8cf9199cbc6d0ab62d75a210bffc18d1ffb5e39ce0ffe0e7200d9b41d62c4fb741aa77ac11b30764373c905c98bc8727faae6e407bcf33bcb52c83b92e97cec526fdb40450313f73ffdb1c03f2ecca14469809862419f831415a23dd44ae60ae9d815358108e1f7ff7cf99b966f35e0173e149f072769adf55151030a0d681ce25c3d9f9ab1033e2bf889def6d66cf8a0338b3f1ff6bb83150fbcd55dbb6cece4033bc7bb86df946a7949d186ecd7b1864fcbc1d234fccb1d57cbfaf5db594098d6f7f50a10dec1640821bb6f38dfd2719abd6d476b934eb42f66bcf9f597e1a6dc5971afd6688cc2acf9e6d843ec250b1d498aa722ead483a1756192928e97b51e4a82d361e6be2c6eb998ea936770f9df586219e2682532b4e032e739a6296da2b0719e37be1f4954491acdb2b67ce6e8d03bc632750868708f77217247617872758737e25a77c26991b4a828431178419b5ed69a7946cdde6b7867c5d9057b967f09c7ea208e3eb279ada37b75f657f19f1370a2dca70a055a7ce2bbc4de2114b84275d57a2c6639ea4fe835b3f52c00c6a1bcd307f3c7ee45cdb9db70b40ff606796a2dcf18e205cae09cdd67d49f77f652e3b460f2ab9f15b115ad454ff04453f5cd79871b591e03a9eafcf85c575d196c0dce506c5f22b0711ebaac766a0486ffc7420afd748d7bf2f819ce55fdba163861a740288b7f0055fb890bf3254087df800fbf86da591c03eebc51873897d5fe08c996efd6bceca4d5a3cb8ccaff3edd1f68107d338acc23f56ee9bab1fb3e062abcbc89e8e35ba8d38e550a014a9341cdd564ac2929759b35b5feb510ee3997ed0618be6afb37a71ed4103471286e52b1df24d9623cfeb4d51cf841fc78aefa7c311456040d67eaddfc63d4c3a1b759f40db6cd86ce4fb3fd283f261da28578fdc516185d20d3b9398fb8b09fbd569ebde883503ee450e3d7633b2c1c73a657994888cd1e3c635c5a147692ab85336935f7f32a3288e98b8854541aa1f4f9df7744d13dee69ff1a671304409200360283c26f2209c102f23b83f3ba532b675ac040593076b08f3c8915cc82fa3648b0d1d15d016b98836116797ed2db22d60e9bc5886e5e18fb0ae7a135228c304fbd44ad268f0213542041bd5f2be0e12f44315ac6be4daa2bccaa3fa7e6eff5346f06dd3394733d5d77e5d7fc8d0b6e5b44a9877beaeb6d07caf9778a98cb8de00f3fe9ebd8691b87ae2a50bfc004d341562cd40fb8e169784cfdd247feca013ae4165ab5228ab7b80c37af0f8b7218c8c2e2caeaf1d7a66499ddd744e192582938b4b6fb3c7e18d9da357c53b7fe43dacff2f0745d742db5fac20fea08cb9a9751418824ecee46d3614b40f50c4f5e5ec785ce16c3610551b7d400a13d1ed06b78e45598fb824a8ce6a2815c520e703bf0c2ed36ec463622183a34d24632018df5c5a7be31e12beeb461caf051e2825b93d2d43ea1c9c90e641d33e3ecb135e4100d050055b4f1e012b1a019d1749ba5f7dc0b94a895c5ffe5a4833ef700", + "expected": "a94d7bf363f32a5a5b6e9f71b2edaa3f2ae31a61000000000000000000000000" + } +] \ No newline at end of file diff --git a/evm/parity/Dockerfile b/evm/parity/Dockerfile index 67c9802..def28d3 100644 --- a/evm/parity/Dockerfile +++ b/evm/parity/Dockerfile @@ -18,6 +18,11 @@ RUN apt-get update \ graphviz git openssh-client \ && rm -rf /var/lib/apt/lists/* +# install python modules needed for benchmarking script +RUN pip3 install durationpy jinja2 pandas + +WORKDIR /root + # install rust RUN curl https://sh.rustup.rs -sSf | \ sh -s -- --default-toolchain stable -y && . $HOME/.cargo/env @@ -34,8 +39,5 @@ RUN cd parity/evmbin && cargo build --release RUN apt-get update RUN apt-get install -y libudev-dev -# install python modules needed for benchmarking script -RUN pip3 install durationpy jinja2 pandas - WORKDIR / CMD /bin/bash diff --git a/evm/scripts/benchevm.py b/evm/scripts/benchevm.py index 73b31e7..2b1802a 100644 --- a/evm/scripts/benchevm.py +++ b/evm/scripts/benchevm.py @@ -7,6 +7,7 @@ import time import datetime import os +import sys import shutil import shlex @@ -14,33 +15,33 @@ RESULT_CSV_OUTPUT_PATH = "/evmraceresults" # must be an absolute path to evm code dir -EVM_CODE_DIR = "/evmrace/evmcode" +EVM_CODE_DIR = "/input_data/evmcode" -INPUT_VECTORS_DIR = "./inputvectors" +INPUT_VECTORS_DIR = "./input_data/input_vectors" EVMONE_BUILD_DIR = "/root/evmone/build" -PARITY_EVM_DIR = "/root/parity/target/release" +PARITY_EVM_DIR = "/parity/target/release" -CITA_EVM_DIR = "/root/cita-vm/target/release" +CITA_EVM_DIR = "/cita-vm/target/release" GETH_EVM_DIR = "/root/go/src/github.com/ethereum/go-ethereum/core/vm/runtime" - -def saveResults(evm_benchmarks): - result_file = os.path.join(RESULT_CSV_OUTPUT_PATH, "evm_benchmarks.csv") +def save_results(evm_name, evm_benchmarks): + result_file = os.path.join(RESULT_CSV_OUTPUT_PATH, "evm_benchmarks_{}.csv".format(evm_name)) # move existing files to old-datetime-folder ts = time.time() date_str = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d') ts_folder_name = "{}-{}".format(date_str, round(ts)) dest_backup_path = os.path.join(RESULT_CSV_OUTPUT_PATH, ts_folder_name) - os.makedirs(dest_backup_path) #for file in glob.glob(r"{}/*.csv".format(RESULT_CSV_OUTPUT_PATH)): if os.path.isfile(result_file): + os.makedirs(dest_backup_path) print("backing up existing {}".format(result_file)) shutil.move(result_file, dest_backup_path) - print("existing csv files backed up to {}".format(dest_backup_path)) + print("existing csv files backed up to {}".format(dest_backup_path)) + # will always be a new file after this. # might move this backup routine to a bash script @@ -59,76 +60,42 @@ def saveResults(evm_benchmarks): writer.writerow(row) +def get_evmone_cmd(codefile, calldata, expected): + cmd_str = "bin/evmone-bench {} {} {} --benchmark_color=false --benchmark_filter=external_evm_code --benchmark_min_time=7".format(codefile, calldata, expected) + return cmd_str + + +def get_parity_cmd(codefile, calldata, expected): + cmd_str = "./parity-evm --code-file {} --input {} --expected {} ".format(codefile, calldata, expected) + return cmd_str + def get_geth_cmd(codefile, calldata, expected): cmd_str = "go test -v -bench BenchmarkEvmCode --codefile {} --input {} --expected {}".format(codefile, calldata, expected) return cmd_str +def get_cita_cmd(codefile, calldata, expected): + cmd_str = "./cita-evm --code-file {} --input {} --expected {} ".format(codefile, calldata, expected) + return cmd_str -""" -runtime mbpro$ go test -v -bench BenchmarkEvmCode --codefile /root/bn128mul.evm --input 039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff --expected 0e9c28772a2a79561257f998c9c31e9b47bb592d54b6936bc00066453f50b27816c1cda062bd6cc07463ba71ff1d299223dd1bb9a6ac5cfe1d57a19c87a229e029a4b5947ed4dca6df8349674078a9b3ea3d06b4373d9d7a50866f3de054285d -=== RUN TestDefaults ---- PASS: TestDefaults (0.00s) -=== RUN TestEVM ---- PASS: TestEVM (0.00s) -=== RUN TestExecute ---- PASS: TestExecute (0.00s) -=== RUN TestCall ---- PASS: TestCall (0.00s) -=== RUN ExampleExecute ---- PASS: ExampleExecute (0.00s) -codefile: /root/bn128mul.evm -code hex length: 29317 -got return bytes: 0e9c28772a2a79561257f998c9c31e9b47bb592d54b6936bc00066453f50b27816c1cda062bd6cc07463ba71ff1d299223dd1bb9a6ac5cfe1d57a19c87a229e029a4b5947ed4dca6df8349674078a9b3ea3d06b4373d9d7a50866f3de054285d -gasUsed: 47561 -goos: darwin -goarch: amd64 -pkg: github.com/ethereum/go-ethereum/core/vm/runtime -BenchmarkEvmCode-12 codefile: /root/bn128mul.evm -code hex length: 29317 -got return bytes: 0e9c28772a2a79561257f998c9c31e9b47bb592d54b6936bc00066453f50b27816c1cda062bd6cc07463ba71ff1d299223dd1bb9a6ac5cfe1d57a19c87a229e029a4b5947ed4dca6df8349674078a9b3ea3d06b4373d9d7a50866f3de054285d -gasUsed: 47561 -codefile: /root/bn128mul.evm -code hex length: 29317 -got return bytes: 0e9c28772a2a79561257f998c9c31e9b47bb592d54b6936bc00066453f50b27816c1cda062bd6cc07463ba71ff1d299223dd1bb9a6ac5cfe1d57a19c87a229e029a4b5947ed4dca6df8349674078a9b3ea3d06b4373d9d7a50866f3de054285d -gasUsed: 47561 - 1000 1363188 ns/op -PASS -ok github.com/ethereum/go-ethereum/core/vm/runtime 2.847s -""" - -def do_geth_bench(geth_cmd): - print("running geth-evm benchmark...\n{}\n".format(geth_cmd)) - geth_cmd = shlex.split(geth_cmd) +def do_evmone_bench(evmone_cmd): + print("running evmone benchmark...\n{}\n".format(evmone_cmd)) + evmone_cmd = shlex.split(evmone_cmd) stdoutlines = [] - with subprocess.Popen(geth_cmd, cwd=GETH_EVM_DIR, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=1, universal_newlines=True) as p: + with subprocess.Popen(evmone_cmd, cwd=EVMONE_BUILD_DIR, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=1, universal_newlines=True) as p: for line in p.stdout: # b'\n'-separated lines print(line, end='') stdoutlines.append(line) # pass bytes as is - p.wait() + p.wait() - nsOpRegex = "\d+\s+([\d]+) ns\/op" - gasregex = "gasUsed: (\d+)" + timeregex = "external_evm_code\s+(\d+) us" + gasregex = "gas_used=([\d\.\w]+)" # maybe --benchmark_format=json is better so dont have to parse "36.775k" - time_line = stdoutlines[-3] - gas_line = stdoutlines[-4] - time_match = re.search(nsOpRegex, time_line) - time = durationpy.from_str("{}ns".format(time_match.group(1))) - gas_match = re.search(gasregex, gas_line) + benchline = stdoutlines[-1] + time_match = re.search(timeregex, benchline) + us_time = durationpy.from_str("{}us".format(time_match.group(1))) + gas_match = re.search(gasregex, benchline) gasused = gas_match.group(1) - return {'gas_used': gasused, 'time': time.total_seconds()} - - -def get_parity_cmd(codefile, calldata, expected): - cmd_str = "./parity-evm --code-file {} --input {} --expected {} ".format(codefile, calldata, expected) - return cmd_str - -""" -~/parity# ./target/release/parity-evm --code-file ./bn128mul.evm --input 039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff --expected "0e9c28772a2a79561257f998c9c31e9b47bb592d54b6936bc00066453f50b27816c1cda062bd6cc07463ba71ff1d299223dd1bb9a6ac5cfe1d57a19c87a229e029a4b5947ed4dca6df8349674078a9b3ea3d06b4373d9d7a50866f3de054285d" -code_hex length: 29317 -return_data: "0e9c28772a2a79561257f998c9c31e9b47bb592d54b6936bc00066453f50b27816c1cda062bd6cc07463ba71ff1d299223dd1bb9a6ac5cfe1d57a19c87a229e029a4b5947ed4dca6df8349674078a9b3ea3d06b4373d9d7a50866f3de054285d" -gas used: 47561 -code avg run time: 12.059442ms -""" + return {'gas_used': gasused, 'time': us_time.total_seconds()} def do_parity_bench(parity_cmd): print("running parity-evm benchmark...\n{}\n".format(parity_cmd)) @@ -151,17 +118,31 @@ def do_parity_bench(parity_cmd): gasused = gas_match.group(1) return {'gas_used': gasused, 'time': time.total_seconds()} +def do_geth_bench(geth_cmd): + print("running geth-evm benchmark...\n{}\n".format(geth_cmd)) + geth_cmd = shlex.split(geth_cmd) + stdoutlines = [] + with subprocess.Popen(geth_cmd, cwd=GETH_EVM_DIR, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=1, universal_newlines=True) as p: + for line in p.stdout: # b'\n'-separated lines + print(line, end='') + stdoutlines.append(line) # pass bytes as is + p.wait() -def get_cita_cmd(codefile, calldata, expected): - cmd_str = "./cita-evm --code-file {} --input {} --expected {} ".format(codefile, calldata, expected) - return cmd_str + nsOpRegex = "\d+\s+([\d]+) ns\/op" + gasregex = "gasUsed: (\d+)" + # maybe --benchmark_format=json is better so dont have to parse "36.775k" + time_line = stdoutlines[-3] + gas_line = stdoutlines[-4] + time_match = re.search(nsOpRegex, time_line) + #print(">> geth_cmd: ", geth_cmd) + #print(">> stdoutlines: ", stdoutlines) + #print(">> time_line: ", time_line) + #print(">> time_match: ", time_match) + time = durationpy.from_str("{}ns".format(time_match.group(1))) + gas_match = re.search(gasregex, gas_line) + gasused = gas_match.group(1) + return {'gas_used': gasused, 'time': time.total_seconds()} -""" -~/cita-vm# ./target/release/cita-evm --code-file /evmrace/evmcode/bn128_mul_weierstrudel.hex --input 039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff --expected "0e9c28772a2a79561257f998c9c31e9b47bb592d54b6936bc00066453f50b27816c1cda062bd6cc07463ba71ff1d299223dd1bb9a6ac5cfe1d57a19c87a229e029a4b5947ed4dca6df8349674078a9b3ea3d06b4373d9d7a50866f3de054285d" -code_hex length: 29316 -gas_used: 75089 -code avg run time: 16.695968ms -""" def do_cita_bench(cita_cmd): print("running cita-evm benchmark...\n{}\n".format(cita_cmd)) @@ -183,65 +164,55 @@ def do_cita_bench(cita_cmd): gasused = gas_match.group(1) return {'gas_used': gasused, 'time': time.total_seconds()} - - - - -def get_evmone_cmd(codefile, calldata, expected): - cmd_str = "bin/evmone-bench {} {} {} --benchmark_color=false --benchmark_filter=external_evm_code --benchmark_min_time=7".format(codefile, calldata, expected) - return cmd_str - - -""" -~/evmone/build# test/evmone-bench sha1code.hex 1605782b00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000006010203040506 5d211bad8f4ee70e16c7d343a838fc344a1ed961000000000000000000000000 --benchmark_filter=bench_evm_code -argv[0] = test/evmone-bench -argv[1] = sha1code.hex -argv[2] = 1605782b00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000006010203040506 -argv[3] = 5d211bad8f4ee70e16c7d343a838fc344a1ed961000000000000000000000000 -argv[4] = --benchmark_filter=bench_evm_code -hex code length:3107 -calldata size:74 -expected:5d211bad8f4ee70e16c7d343a838fc344a1ed961000000000000000000000000 -2019-04-10 15:57:52 -Running test/evmone-bench -Run on (4 X 2294.68 MHz CPU s) -CPU Caches: - L1 Data 32K (x2) - L1 Instruction 32K (x2) - L2 Unified 256K (x2) - L3 Unified 51200K (x2) ----------------------------------------------------------------------- -Benchmark Time CPU Iterations UserCounters... ----------------------------------------------------------------------- -bench_evm_code 152 us 152 us 4694 gas_rate=241.788M/s gas_used=36.775k -""" - -def do_evmone_bench(evmone_cmd): - print("running evmone benchmark...\n{}\n".format(evmone_cmd)) - evmone_cmd = shlex.split(evmone_cmd) - stdoutlines = [] - with subprocess.Popen(evmone_cmd, cwd=EVMONE_BUILD_DIR, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=1, universal_newlines=True) as p: - for line in p.stdout: # b'\n'-separated lines - print(line, end='') - stdoutlines.append(line) # pass bytes as is - p.wait() - - timeregex = "external_evm_code\s+(\d+) us" - gasregex = "gas_used=([\d\.\w]+)" - # maybe --benchmark_format=json is better so dont have to parse "36.775k" - benchline = stdoutlines[-1] - time_match = re.search(timeregex, benchline) - us_time = durationpy.from_str("{}us".format(time_match.group(1))) - gas_match = re.search(gasregex, benchline) - gasused = gas_match.group(1) - return {'gas_used': gasused, 'time': us_time.total_seconds()} - - -def main(): - evmcodefiles = [fname for fname in os.listdir(EVM_CODE_DIR) if fname.endswith(".hex")] +def bench_evm(evm_name, input, codefilepath, shift_suffix): + calldata = input['input'] + expected = input['expected'] + test_name = input['name'] + shift_suffix + + evm_result = {} + if evm_name == 'evmone': + evmone_bench_cmd = get_evmone_cmd(codefilepath, calldata, expected) + evmone_bench_result = do_evmone_bench(evmone_bench_cmd) + + print("got evmone_bench_result:", evmone_bench_result) + evm_result['engine'] = 'evmone' + evm_result['test_name'] = test_name + evm_result['total_time'] = evmone_bench_result['time'] + evm_result['gas_used'] = evmone_bench_result['gas_used'] + + if evm_name == "parity": + parity_bench_cmd = get_parity_cmd(codefilepath, calldata, expected) + parity_bench_result = do_parity_bench(parity_bench_cmd) + + evm_result['engine'] = 'parity-evm' + evm_result['test_name'] = test_name + evm_result['gas_used'] = parity_bench_result['time'] + + if evm_name == "geth": + geth_bench_cmd = get_geth_cmd(codefilepath, calldata, expected) + geth_bench_result = do_geth_bench(geth_bench_cmd) + + evm_result['engine'] = "geth-evm" + evm_result['test_name'] = test_name + evm_result['total_time'] = geth_bench_result['time'] + evm_result['gas_used'] = geth_bench_result['gas_used'] + + if evm_name == "cita-vm": + cita_bench_cmd = get_cita_cmd(codefilepath, calldata, expected) + cita_bench_result = do_cita_bench(cita_bench_cmd) + + evm_result['engine'] = "cita-evm" + evm_result['test_name'] = test_name + evm_result['total_time'] = cita_bench_result['time'] + evm_result['gas_used'] = cita_bench_result['gas_used'] + + return evm_result + +def main(evm_name): + evmcodefiles = [fname for fname in os.listdir(EVM_CODE_DIR) if fname.endswith('.hex')] evm_benchmarks = [] for codefile in evmcodefiles: - print("start benching: ", codefile) + print('start benching: ', codefile) codefilepath = os.path.join(EVM_CODE_DIR, codefile) benchname = codefile.replace(".hex", "") inputsfilename = benchname @@ -254,56 +225,20 @@ def main(): with open(inputs_file_path) as f: bench_inputs = json.load(f) for input in bench_inputs: - print("bench input:", input['name']) - calldata = input['input'] - expected = input['expected'] - evmone_bench_cmd = get_evmone_cmd(codefilepath, calldata, expected) - evmone_bench_result = do_evmone_bench(evmone_bench_cmd) - test_name = input['name'] + shift_suffix - # evm_benchmarks[input['name']] = evmone_bench_result - print("got evmone_bench_result:", evmone_bench_result) - - evmone_result = {} - evmone_result['engine'] = "evmone" - evmone_result['test_name'] = test_name - evmone_result['total_time'] = evmone_bench_result['time'] - evmone_result['gas_used'] = evmone_bench_result['gas_used'] - evm_benchmarks.append(evmone_result) - - parity_bench_cmd = get_parity_cmd(codefilepath, calldata, expected) - parity_bench_result = do_parity_bench(parity_bench_cmd) - parity_result = {} - parity_result['engine'] = "parity-evm" - parity_result['test_name'] = test_name - parity_result['total_time'] = parity_bench_result['time'] - parity_result['gas_used'] = parity_bench_result['gas_used'] - evm_benchmarks.append(parity_result) - - geth_bench_cmd = get_geth_cmd(codefilepath, calldata, expected) - geth_bench_result = do_geth_bench(geth_bench_cmd) - geth_result = {} - geth_result['engine'] = "geth-evm" - geth_result['test_name'] = test_name - geth_result['total_time'] = geth_bench_result['time'] - geth_result['gas_used'] = geth_bench_result['gas_used'] - evm_benchmarks.append(geth_result) - - cita_bench_cmd = get_cita_cmd(codefilepath, calldata, expected) - cita_bench_result = do_cita_bench(cita_bench_cmd) - cita_result = {} - cita_result['engine'] = "cita-evm" - cita_result['test_name'] = test_name - cita_result['total_time'] = cita_bench_result['time'] - cita_result['gas_used'] = cita_bench_result['gas_used'] - evm_benchmarks.append(cita_result) - - print("done with input:", test_name) - - print("done benching: ", benchname) - - print("got evm_benchmarks:", evm_benchmarks) - - saveResults(evm_benchmarks) + print("bench input: ", input['name']) + + evm_result = bench_evm(evm_name, input, codefilepath, shift_suffix) + evm_benchmarks.append(evm_result) + + + save_results(evm_name, evm_benchmarks) + +def usage(): + print("newbench.py ") if __name__ == "__main__": - main() \ No newline at end of file + if len(sys.argv) < 2: + usage() + + evm_name = sys.argv[1] + main(evm_name) diff --git a/evm/scripts/run_bench.sh b/evm/scripts/run_bench.sh new file mode 100755 index 0000000..dcadc93 --- /dev/null +++ b/evm/scripts/run_bench.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# Run evmone benchmarks +docker run -v $(pwd)/evmraceresults:/evmraceresults -v $(pwd)/scripts:/scripts -v $(pwd)/input_data:/input_data -it evmone-bench /usr/bin/python3 /scripts/benchevm.py evmone + +# Run Parity benchmarks +docker run -v $(pwd)/evmraceresults:/evmraceresults -v $(pwd)/scripts:/scripts -v $(pwd)/input_data:/input_data -it parity-bench /usr/bin/python3 /scripts/benchevm.py parity + +# Run Geth benchmarks +docker run -v $(pwd)/evmraceresults:/evmraceresults -v $(pwd)/scripts:/scripts -v $(pwd)/input_data:/input_data -it geth-bench /usr/bin/python3 /scripts/benchevm.py geth + +# Run cita-vm benchmarks +docker run -v $(pwd)/evmraceresults:/evmraceresults -v $(pwd)/scripts:/scripts -v $(pwd)/input_data:/input_data -it cita-vm-bench /usr/bin/python3 /scripts/benchevm.py cita-vm + +echo engine,test_name,total_time,gas_used > evmraceresults/evm_benchmarks.csv +lines=$(wc -l evmraceresults/evm_benchmarks_evmone.csv | cut -d ' ' -f1) +lines=$((lines-1)) +for i in $(seq $lines) +do + counting=$((i+1)) + head -n $counting evmraceresults/evm_benchmarks_evmone.csv | tail -n 1 >> evmraceresults/evm_benchmarks.csv + head -n $counting evmraceresults/evm_benchmarks_parity.csv | tail -n 1 >> evmraceresults/evm_benchmarks.csv + head -n $counting evmraceresults/evm_benchmarks_geth.csv | tail -n 1 >> evmraceresults/evm_benchmarks.csv + head -n $counting evmraceresults/evm_benchmarks_cita-vm.csv | tail -n 1 >> evmraceresults/evm_benchmarks.csv +done + +