From 21241b7370b45ff42ea3a9ca7e429248c77a2481 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 3 Jan 2014 15:28:21 +0000 Subject: [PATCH] RIP-EMD160 implementation for the VM. Additional VM instructions. --- libethereum/Common.cpp | 53 +++++ libethereum/Common.h | 2 + libethereum/VirtualMachine.cpp | 91 ++++++++- libethereum/VirtualMachine.h | 35 +++- libethereum/rmd160.cpp | 351 +++++++++++++++++++++++++++++++++ libethereum/rmd160.h | 46 +++++ 6 files changed, 567 insertions(+), 11 deletions(-) create mode 100644 libethereum/rmd160.cpp create mode 100644 libethereum/rmd160.h diff --git a/libethereum/Common.cpp b/libethereum/Common.cpp index 910cd233e..34a7a7601 100644 --- a/libethereum/Common.cpp +++ b/libethereum/Common.cpp @@ -1,2 +1,55 @@ #include "Common.h" +#include "rmd160.h" +using namespace std; +using namespace eth; +/* collect four bytes into one word: */ +#define BYTES_TO_DWORD(strptr) \ + (((uint32_t) *((strptr)+3) << 24) | \ + ((uint32_t) *((strptr)+2) << 16) | \ + ((uint32_t) *((strptr)+1) << 8) | \ + ((uint32_t) *(strptr))) + +u256 eth::ripemd160(fConstBytes _message) +/* + * returns RMD(message) + * message should be a string terminated by '\0' + */ +{ + static const uint RMDsize = 160; + uint32_t MDbuf[RMDsize/32]; /* contains (A, B, C, D(, E)) */ + static byte hashcode[RMDsize/8]; /* for final hash-value */ + uint32_t X[16]; /* current 16-word chunk */ + unsigned int i; /* counter */ + uint32_t length; /* length in bytes of message */ + uint32_t nbytes; /* # of bytes not yet processed */ + + /* initialize */ + MDinit(MDbuf); + length = _message.size(); + auto message = _message.data(); + + /* process message in 16-word chunks */ + for (nbytes=length; nbytes > 63; nbytes-=64) { + for (i=0; i<16; i++) { + X[i] = BYTES_TO_DWORD(message); + message += 4; + } + compress(MDbuf, X); + } /* length mod 64 bytes left */ + + /* finish: */ + MDfinish(MDbuf, message, length, 0); + + for (i=0; i>2]; /* implicit cast to byte */ + hashcode[i+1] = (MDbuf[i>>2] >> 8); /* extracts the 8 least */ + hashcode[i+2] = (MDbuf[i>>2] >> 16); /* significant bits. */ + hashcode[i+3] = (MDbuf[i>>2] >> 24); + } + + u256 ret = 0; + for (i = 0; i < RMDsize / 8; ++i) + ret = (ret << 8) | hashcode[i]; + return ret; +} diff --git a/libethereum/Common.h b/libethereum/Common.h index d5b6d7146..4155815a7 100644 --- a/libethereum/Common.h +++ b/libethereum/Common.h @@ -74,4 +74,6 @@ template uint commonPrefix(_T const& _t, _U const& _u) return s; } +u256 ripemd160(fConstBytes _message); + } diff --git a/libethereum/VirtualMachine.cpp b/libethereum/VirtualMachine.cpp index f4d3f49be..9e2a0a107 100644 --- a/libethereum/VirtualMachine.cpp +++ b/libethereum/VirtualMachine.cpp @@ -1,3 +1,4 @@ +#include "sha256.h" #include "VirtualMachine.h" using namespace std; using namespace eth; @@ -34,56 +35,140 @@ void VirtualMachine::go() require(2); m_stack[m_stack.size() - 2] += m_stack.back(); m_stack.pop_back(); + break; case Instruction::MUL: //pops two items and pushes S[-1] * S[-2] mod 2^256. require(2); m_stack[m_stack.size() - 2] *= m_stack.back(); m_stack.pop_back(); + break; case Instruction::SUB: require(2); m_stack[m_stack.size() - 2] = m_stack.back() - m_stack[m_stack.size() - 2]; m_stack.pop_back(); + break; case Instruction::DIV: require(2); m_stack[m_stack.size() - 2] = m_stack.back() / m_stack[m_stack.size() - 2]; m_stack.pop_back(); + break; case Instruction::SDIV: require(2); (s256&)m_stack[m_stack.size() - 2] = (s256&)m_stack.back() / (s256&)m_stack[m_stack.size() - 2]; m_stack.pop_back(); + break; case Instruction::MOD: require(2); m_stack[m_stack.size() - 2] = m_stack.back() % m_stack[m_stack.size() - 2]; m_stack.pop_back(); + break; case Instruction::SMOD: require(2); (s256&)m_stack[m_stack.size() - 2] = (s256&)m_stack.back() % (s256&)m_stack[m_stack.size() - 2]; m_stack.pop_back(); + break; case Instruction::EXP: + { + // TODO: better implementation? require(2); -// (s256&)m_stack[m_stack.size() - 2] = pow(m_stack.back(), m_stack[m_stack.size() - 2]); -// m_stack.pop_back(); + auto n = m_stack.back(); + auto x = m_stack[m_stack.size() - 2]; + m_stack.pop_back(); + for (u256 i = 0; i < x; ++i) + n *= n; + m_stack.back() = n; + break; + } case Instruction::NEG: + require(1); + m_stack.back() = ~(m_stack.back() - 1); + break; case Instruction::LT: + require(2); + m_stack[m_stack.size() - 2] = m_stack.back() < m_stack[m_stack.size() - 2] ? 1 : 0; + m_stack.pop_back(); + break; case Instruction::LE: + require(2); + m_stack[m_stack.size() - 2] = m_stack.back() <= m_stack[m_stack.size() - 2] ? 1 : 0; + m_stack.pop_back(); + break; case Instruction::GT: + require(2); + m_stack[m_stack.size() - 2] = m_stack.back() > m_stack[m_stack.size() - 2] ? 1 : 0; + m_stack.pop_back(); + break; case Instruction::GE: + require(2); + m_stack[m_stack.size() - 2] = m_stack.back() >= m_stack[m_stack.size() - 2] ? 1 : 0; + m_stack.pop_back(); + break; case Instruction::EQ: + require(2); + m_stack[m_stack.size() - 2] = m_stack.back() == m_stack[m_stack.size() - 2] ? 1 : 0; + m_stack.pop_back(); + break; case Instruction::NOT: + require(1); + m_stack.back() = m_stack.back() ? 0 : 1; + m_stack.pop_back(); + break; case Instruction::MYADDRESS: - case Instruction::MYCREATOR: + m_stack.push_back(m_myAddress); + break; case Instruction::TXSENDER: + m_stack.push_back(m_txSender); + break; case Instruction::TXVALUE: + m_stack.push_back(m_txValue); + break; case Instruction::TXFEE: + m_stack.push_back(m_txFee); + break; case Instruction::TXDATAN: + m_stack.push_back(m_txData.size()); + break; case Instruction::TXDATA: + require(1); + m_stack.back() = m_stack.back() < m_txData.size() ? m_txData[(uint)m_stack.back()] : 0; + break; case Instruction::BLK_PREVHASH: + m_stack.push_back(m_previousBlock.hash); + break; case Instruction::BLK_COINBASE: + m_stack.push_back(m_currentBlock.coinbase); + break; case Instruction::BLK_TIMESTAMP: + m_stack.push_back(m_currentBlock.timestamp); + break; case Instruction::BLK_NUMBER: + m_stack.push_back(m_currentBlock.number); + break; case Instruction::BLK_DIFFICULTY: + m_stack.push_back(m_currentBlock.difficulty); + break; case Instruction::SHA256: case Instruction::RIPEMD160: + { + uint s = (uint)min(m_stack.back(), (u256)(m_stack.size() - 1) * 32); + bytes b(s); + uint i = 0; + for (; s; s = (s >= 32 ? s - 32 : 0), i += 32) + { + m_stack.pop_back(); + u256 v = m_stack.back(); + int sz = (int)min(32, s) - 1; // sz is one fewer than the number of bytes we're interested in. + v >>= ((31 - sz) * 8); // kill unused low-order bytes. + for (int j = 0; j <= sz; ++j, v >>= 8) // cycle through bytes, starting at low-order end. + b[i + sz - j] = (byte)(v & 0xff); // set each 32-byte (256-bit) chunk in reverse - (i.e. we want to put low-order last). + } + if (inst == Instruction::SHA256) + m_stack.back() = sha256(b); + else + m_stack.back() = ripemd160(&b); + + break; + } case Instruction::ECMUL: case Instruction::ECADD: case Instruction::ECSIGN: diff --git a/libethereum/VirtualMachine.h b/libethereum/VirtualMachine.h index 8076be348..34f85d89b 100644 --- a/libethereum/VirtualMachine.h +++ b/libethereum/VirtualMachine.h @@ -23,14 +23,13 @@ enum class Instruction: uint8_t SMOD, ///< Rx Ry Rz - like MOD, but for signed values just like SDIV (using Python's convention with negative numbers) EXP, ///< Rx Ry Rz - sets Rz <- Rx ^ Ry mod 2^256 NEG, ///< Rx Ry - sets Ry <- 2^256 - Rx - LT = 0x10, ///< Rx Ry Rz - sets Rz <- 1 if Rx < Ry else 0 + LT, ///< Rx Ry Rz - sets Rz <- 1 if Rx < Ry else 0 LE, ///< Rx Ry Rz - sets Rz <- 1 if Rx <= Ry else 0 GT, ///< Rx Ry Rz - sets Rz <- 1 if Rx > Ry else 0 GE, ///< Rx Ry Rz - sets Rz <- 1 if Rx >= Ry else 0 EQ, ///< Rx Ry Rz - sets Rz <- 1 if Rx = Ry else 0 NOT, ///< Rx Ry - sets Ry <- 1 if Rx = 0 else 0 - MYADDRESS = 0x20, ///< Rx - sets Rx to the contract's own address - MYCREATOR, ///< Rx - sets Rx to the contract's own address + MYADDRESS = 0x10, ///< Rx - sets Rx to the contract's own address TXSENDER, ///< pushes the transaction sender TXVALUE , ///< pushes the transaction value TXFEE, ///< pushes the transaction fee @@ -41,14 +40,14 @@ enum class Instruction: uint8_t BLK_TIMESTAMP, ///< pushes the timestamp of the current block BLK_NUMBER, ///< pushes the current block number BLK_DIFFICULTY, ///< pushes the difficulty of the current block - SHA256 = 0x30, ///< sets Ry <- SHA256(Rx) + SHA256 = 0x20, ///< sets Ry <- SHA256(Rx) RIPEMD160, ///< Rx Ry - sets Ry <- RIPEMD160(Rx) ECMUL, ///< Rx Ry Rz Ra Rb - sets (Ra, Rb) = Rz * (Rx, Ry) in secp256k1, using (0,0) for the point at infinity ECADD, ///< Rx Ry Rz Ra Rb Rc - sets (Rb, Rc) = (Rx, Ry) + (Ra, Rb) ECSIGN, ///< Rx Ry Rz Ra Rb - sets(Rz, Ra, Rb)as the(r,s,prefix)values of an Electrum-style RFC6979 deterministic signature ofRxwith private keyRy` ECRECOVER, ///< Rx Ry Rz Ra Rb Rc - sets(Rb, Rc)as the public key from the signature(Ry, Rz, Ra)of the message hashRx` ECVALID, ///< Rx Ry Rz Ra Rb Rc - sets(Rb, Rc)as the public key from the signature(Ry, Rz, Ra)of the message hashRx` - PUSH = 0x40, + PUSH = 0x30, POP, DUP, DUPN, @@ -56,18 +55,27 @@ enum class Instruction: uint8_t SWAPN, LOAD, STORE, - JMP = 0x50, ///< Rx - sets the index pointer to the value at Rx + JMP = 0x40, ///< Rx - sets the index pointer to the value at Rx JMPI, ///< Rx Ry - if Rx != 0, sets the index pointer to Ry IND, ///< pushes the index pointer. - EXTRO = 0x60, ///< Rx Ry Rz - looks at the contract at address Rx and its memory state Ry, and outputs the result to Rz + EXTRO = 0x50, ///< Rx Ry Rz - looks at the contract at address Rx and its memory state Ry, and outputs the result to Rz BALANCE, ///< Rx - returns the ether balance of address Rx - MKTX = 0x70, ///< Rx Ry Rz Rw Rv - sends Ry ether to Rx plus Rz fee with Rw data items starting from memory index Rv (and then reading to (Rv + 1), (Rv + 2) etc). Note that if Rx = 0 then this creates a new contract. + MKTX = 0x60, ///< Rx Ry Rz Rw Rv - sends Ry ether to Rx plus Rz fee with Rw data items starting from memory index Rv (and then reading to (Rv + 1), (Rv + 2) etc). Note that if Rx = 0 then this creates a new contract. SUICIDE = 0xff ///< Rx - destroys the contract and clears all memory, sending the entire balance plus the negative fee from clearing memory minus TXFEE to the address }; class BadInstruction: public std::exception {}; class StackTooSmall: public std::exception { public: StackTooSmall(uint _req, uint _got): req(_req), got(_got) {} uint req; uint got; }; +struct BlockInfo +{ + u256 hash; + u256 coinbase; + u256 timestamp; + u256 number; + u256 difficulty; +}; + class VirtualMachine { public: @@ -91,6 +99,17 @@ private: u256 m_extroFee; u256 m_minerFee; u256 m_voidFee; + + u256 m_myAddress; + u256 m_txSender; + u256 m_txValue; + u256 m_txFee; + std::vector m_txData; + + BlockInfo m_previousBlock; + BlockInfo m_currentBlock; + + }; } diff --git a/libethereum/rmd160.cpp b/libethereum/rmd160.cpp new file mode 100644 index 000000000..46abe8910 --- /dev/null +++ b/libethereum/rmd160.cpp @@ -0,0 +1,351 @@ +/********************************************************************\ + * + * FILE: rmd160.c + * + * CONTENTS: A sample C-implementation of the RIPEMD-160 + * hash-function. + * TARGET: any computer with an ANSI C compiler + * + * AUTHOR: Antoon Bosselaers, ESAT-COSIC + * DATE: 1 March 1996 + * VERSION: 1.0 + * + * Copyright (c) Katholieke Universiteit Leuven + * 1996, All Rights Reserved + * +\********************************************************************/ + +/* header files */ +#include +#include +#include +#include "rmd160.h" + +#include + +/********************************************************************/ + +/* typedef 8 and 32 bit types, resp. */ +/* adapt these, if necessary, + for your operating system and compiler */ +typedef unsigned char byte; +typedef uint32_t dword; + +/* if this line causes a compiler error, + adapt the defintion of dword above */ +typedef int the_correct_size_was_chosen [sizeof (dword) == 4? 1: -1]; + +/********************************************************************/ + +/* macro definitions */ + + +/* ROL(x, n) cyclically rotates x over n bits to the left */ +/* x must be of an unsigned 32 bits type and 0 <= n < 32. */ +#define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* the five basic functions F(), G() and H() */ +#define F(x, y, z) ((x) ^ (y) ^ (z)) +#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define H(x, y, z) (((x) | ~(y)) ^ (z)) +#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define J(x, y, z) ((x) ^ ((y) | ~(z))) + +/* the ten basic operations FF() through III() */ +#define FF(a, b, c, d, e, x, s) {\ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define GG(a, b, c, d, e, x, s) {\ + (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define HH(a, b, c, d, e, x, s) {\ + (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define II(a, b, c, d, e, x, s) {\ + (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define JJ(a, b, c, d, e, x, s) {\ + (a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define FFF(a, b, c, d, e, x, s) {\ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define GGG(a, b, c, d, e, x, s) {\ + (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define HHH(a, b, c, d, e, x, s) {\ + (a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define III(a, b, c, d, e, x, s) {\ + (a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define JJJ(a, b, c, d, e, x, s) {\ + (a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } + +/********************************************************************/ + +void MDinit(dword *MDbuf) +{ + MDbuf[0] = 0x67452301UL; + MDbuf[1] = 0xefcdab89UL; + MDbuf[2] = 0x98badcfeUL; + MDbuf[3] = 0x10325476UL; + MDbuf[4] = 0xc3d2e1f0UL; + + return; +} + +/********************************************************************/ + +void compress(dword *MDbuf, dword *X) +{ + dword aa = MDbuf[0], bb = MDbuf[1], cc = MDbuf[2], + dd = MDbuf[3], ee = MDbuf[4]; + dword aaa = MDbuf[0], bbb = MDbuf[1], ccc = MDbuf[2], + ddd = MDbuf[3], eee = MDbuf[4]; + + /* round 1 */ + FF(aa, bb, cc, dd, ee, X[ 0], 11); + FF(ee, aa, bb, cc, dd, X[ 1], 14); + FF(dd, ee, aa, bb, cc, X[ 2], 15); + FF(cc, dd, ee, aa, bb, X[ 3], 12); + FF(bb, cc, dd, ee, aa, X[ 4], 5); + FF(aa, bb, cc, dd, ee, X[ 5], 8); + FF(ee, aa, bb, cc, dd, X[ 6], 7); + FF(dd, ee, aa, bb, cc, X[ 7], 9); + FF(cc, dd, ee, aa, bb, X[ 8], 11); + FF(bb, cc, dd, ee, aa, X[ 9], 13); + FF(aa, bb, cc, dd, ee, X[10], 14); + FF(ee, aa, bb, cc, dd, X[11], 15); + FF(dd, ee, aa, bb, cc, X[12], 6); + FF(cc, dd, ee, aa, bb, X[13], 7); + FF(bb, cc, dd, ee, aa, X[14], 9); + FF(aa, bb, cc, dd, ee, X[15], 8); + + /* round 2 */ + GG(ee, aa, bb, cc, dd, X[ 7], 7); + GG(dd, ee, aa, bb, cc, X[ 4], 6); + GG(cc, dd, ee, aa, bb, X[13], 8); + GG(bb, cc, dd, ee, aa, X[ 1], 13); + GG(aa, bb, cc, dd, ee, X[10], 11); + GG(ee, aa, bb, cc, dd, X[ 6], 9); + GG(dd, ee, aa, bb, cc, X[15], 7); + GG(cc, dd, ee, aa, bb, X[ 3], 15); + GG(bb, cc, dd, ee, aa, X[12], 7); + GG(aa, bb, cc, dd, ee, X[ 0], 12); + GG(ee, aa, bb, cc, dd, X[ 9], 15); + GG(dd, ee, aa, bb, cc, X[ 5], 9); + GG(cc, dd, ee, aa, bb, X[ 2], 11); + GG(bb, cc, dd, ee, aa, X[14], 7); + GG(aa, bb, cc, dd, ee, X[11], 13); + GG(ee, aa, bb, cc, dd, X[ 8], 12); + + /* round 3 */ + HH(dd, ee, aa, bb, cc, X[ 3], 11); + HH(cc, dd, ee, aa, bb, X[10], 13); + HH(bb, cc, dd, ee, aa, X[14], 6); + HH(aa, bb, cc, dd, ee, X[ 4], 7); + HH(ee, aa, bb, cc, dd, X[ 9], 14); + HH(dd, ee, aa, bb, cc, X[15], 9); + HH(cc, dd, ee, aa, bb, X[ 8], 13); + HH(bb, cc, dd, ee, aa, X[ 1], 15); + HH(aa, bb, cc, dd, ee, X[ 2], 14); + HH(ee, aa, bb, cc, dd, X[ 7], 8); + HH(dd, ee, aa, bb, cc, X[ 0], 13); + HH(cc, dd, ee, aa, bb, X[ 6], 6); + HH(bb, cc, dd, ee, aa, X[13], 5); + HH(aa, bb, cc, dd, ee, X[11], 12); + HH(ee, aa, bb, cc, dd, X[ 5], 7); + HH(dd, ee, aa, bb, cc, X[12], 5); + + /* round 4 */ + II(cc, dd, ee, aa, bb, X[ 1], 11); + II(bb, cc, dd, ee, aa, X[ 9], 12); + II(aa, bb, cc, dd, ee, X[11], 14); + II(ee, aa, bb, cc, dd, X[10], 15); + II(dd, ee, aa, bb, cc, X[ 0], 14); + II(cc, dd, ee, aa, bb, X[ 8], 15); + II(bb, cc, dd, ee, aa, X[12], 9); + II(aa, bb, cc, dd, ee, X[ 4], 8); + II(ee, aa, bb, cc, dd, X[13], 9); + II(dd, ee, aa, bb, cc, X[ 3], 14); + II(cc, dd, ee, aa, bb, X[ 7], 5); + II(bb, cc, dd, ee, aa, X[15], 6); + II(aa, bb, cc, dd, ee, X[14], 8); + II(ee, aa, bb, cc, dd, X[ 5], 6); + II(dd, ee, aa, bb, cc, X[ 6], 5); + II(cc, dd, ee, aa, bb, X[ 2], 12); + + /* round 5 */ + JJ(bb, cc, dd, ee, aa, X[ 4], 9); + JJ(aa, bb, cc, dd, ee, X[ 0], 15); + JJ(ee, aa, bb, cc, dd, X[ 5], 5); + JJ(dd, ee, aa, bb, cc, X[ 9], 11); + JJ(cc, dd, ee, aa, bb, X[ 7], 6); + JJ(bb, cc, dd, ee, aa, X[12], 8); + JJ(aa, bb, cc, dd, ee, X[ 2], 13); + JJ(ee, aa, bb, cc, dd, X[10], 12); + JJ(dd, ee, aa, bb, cc, X[14], 5); + JJ(cc, dd, ee, aa, bb, X[ 1], 12); + JJ(bb, cc, dd, ee, aa, X[ 3], 13); + JJ(aa, bb, cc, dd, ee, X[ 8], 14); + JJ(ee, aa, bb, cc, dd, X[11], 11); + JJ(dd, ee, aa, bb, cc, X[ 6], 8); + JJ(cc, dd, ee, aa, bb, X[15], 5); + JJ(bb, cc, dd, ee, aa, X[13], 6); + + /* parallel round 1 */ + JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8); + JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9); + JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13); + JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15); + JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5); + JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7); + JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); + JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14); + JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12); + JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); + + /* parallel round 2 */ + III(eee, aaa, bbb, ccc, ddd, X[ 6], 9); + III(ddd, eee, aaa, bbb, ccc, X[11], 13); + III(ccc, ddd, eee, aaa, bbb, X[ 3], 15); + III(bbb, ccc, ddd, eee, aaa, X[ 7], 7); + III(aaa, bbb, ccc, ddd, eee, X[ 0], 12); + III(eee, aaa, bbb, ccc, ddd, X[13], 8); + III(ddd, eee, aaa, bbb, ccc, X[ 5], 9); + III(ccc, ddd, eee, aaa, bbb, X[10], 11); + III(bbb, ccc, ddd, eee, aaa, X[14], 7); + III(aaa, bbb, ccc, ddd, eee, X[15], 7); + III(eee, aaa, bbb, ccc, ddd, X[ 8], 12); + III(ddd, eee, aaa, bbb, ccc, X[12], 7); + III(ccc, ddd, eee, aaa, bbb, X[ 4], 6); + III(bbb, ccc, ddd, eee, aaa, X[ 9], 15); + III(aaa, bbb, ccc, ddd, eee, X[ 1], 13); + III(eee, aaa, bbb, ccc, ddd, X[ 2], 11); + + /* parallel round 3 */ + HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); + HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7); + HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15); + HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11); + HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8); + HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); + HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6); + HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14); + HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); + HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13); + HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); + HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14); + HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); + HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13); + HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7); + HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); + + /* parallel round 4 */ + GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15); + GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5); + GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8); + GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11); + GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14); + GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); + GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); + GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14); + GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6); + GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); + GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12); + GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); + GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12); + GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5); + GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); + GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); + + /* parallel round 5 */ + FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8); + FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5); + FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12); + FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9); + FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12); + FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5); + FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14); + FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6); + FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8); + FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13); + FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6); + FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5); + FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15); + FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13); + FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11); + FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11); + + /* combine results */ + ddd += cc + MDbuf[1]; /* final result for MDbuf[0] */ + MDbuf[1] = MDbuf[2] + dd + eee; + MDbuf[2] = MDbuf[3] + ee + aaa; + MDbuf[3] = MDbuf[4] + aa + bbb; + MDbuf[4] = MDbuf[0] + bb + ccc; + MDbuf[0] = ddd; + + return; +} + +/********************************************************************/ + +void MDfinish(dword *MDbuf, byte const *strptr, dword lswlen, dword mswlen) +{ + unsigned int i; /* counter */ + dword X[16]; /* message words */ + + memset(X, 0, 16*sizeof(dword)); + + /* put bytes from strptr into X */ + for (i=0; i<(lswlen&63); i++) { + /* byte i goes into word X[i div 4] at pos. 8*(i mod 4) */ + X[i>>2] ^= (dword) *strptr++ << (8 * (i&3)); + } + + /* append the bit m_n == 1 */ + X[(lswlen>>2)&15] ^= (dword)1 << (8*(lswlen&3) + 7); + + if ((lswlen & 63) > 55) { + /* length goes to next block */ + compress(MDbuf, X); + memset(X, 0, 16*sizeof(dword)); + } + + /* append length in bits*/ + X[14] = lswlen << 3; + X[15] = (lswlen >> 29) | (mswlen << 3); + compress(MDbuf, X); + + return; +} + +/************************ end of file rmd160.c **********************/ diff --git a/libethereum/rmd160.h b/libethereum/rmd160.h new file mode 100644 index 000000000..f4493098c --- /dev/null +++ b/libethereum/rmd160.h @@ -0,0 +1,46 @@ +/********************************************************************\ + * + * FILE: rmd160.h + * + * CONTENTS: Header file for a sample C-implementation of the + * RIPEMD-160 hash-function. + * TARGET: any computer with an ANSI C compiler + * + * AUTHOR: Antoon Bosselaers, ESAT-COSIC + * DATE: 1 March 1996 + * VERSION: 1.0 + * + * Copyright (c) Katholieke Universiteit Leuven + * 1996, All Rights Reserved + * +\********************************************************************/ + +#ifndef RMD160H /* make sure this file is read only once */ +#define RMD160H + +/********************************************************************/ + +/* function prototypes */ + +void MDinit(uint32_t *MDbuf); +/* + * initializes MDbuffer to "magic constants" + */ + +void compress(uint32_t *MDbuf, uint32_t *X); +/* + * the compression function. + * transforms MDbuf using message bytes X[0] through X[15] + */ + +void MDfinish(uint32_t *MDbuf, unsigned char const *strptr, uint32_t lswlen, uint32_t mswlen); +/* + * puts bytes from strptr into X and pad out; appends length + * and finally, compresses the last block(s) + * note: length in bits == 8 * (lswlen + 2^32 mswlen). + * note: there are (lswlen mod 64) bytes left in strptr. + */ + +#endif /* RMD160H */ + +/*********************** end of file rmd160.h ***********************/