diff --git a/lib/index.js b/lib/index.js index 9367bc980a8..805c94ecea5 100644 --- a/lib/index.js +++ b/lib/index.js @@ -11,6 +11,7 @@ const num01 = require('./precompiled/01-ecrecover.js') const num02 = require('./precompiled/02-sha256.js') const num03 = require('./precompiled/03-ripemd160.js') const num04 = require('./precompiled/04-identity.js') +const num05 = require('./precompiled/05-modexp.js') module.exports = VM @@ -46,9 +47,10 @@ function VM (opts = {}) { this._precompiled['0000000000000000000000000000000000000002'] = num02 this._precompiled['0000000000000000000000000000000000000003'] = num03 this._precompiled['0000000000000000000000000000000000000004'] = num04 + this._precompiled['0000000000000000000000000000000000000005'] = num05 if (this.opts.activatePrecompiles) { - for (var i = 1; i <= 4; i++) { + for (var i = 1; i <= 5; i++) { this.trie.put(Buffer.from(new BN(i).toArray('be', 20)), new Account().serialize()) } } diff --git a/lib/precompiled/05-modexp.js b/lib/precompiled/05-modexp.js new file mode 100644 index 00000000000..522cee709b3 --- /dev/null +++ b/lib/precompiled/05-modexp.js @@ -0,0 +1,45 @@ +const utils = require('ethereumjs-util') +const BN = utils.BN +const error = require('../constants.js').ERROR + +const Gmodexpbase = 45 +const Garithword = 6 +const Gquaddivisor = 32 + +module.exports = function (opts) { + var results = {} + + var i = 0 + var Blen = new BN(data.slice(i, 32)).toNumber() + i += 32 + var B = new BN(data.slice(i, i + Blen)) + i += Blen + var Elen = new BN(data.slice(i, i + 32)).toNumber() + i += 32 + var E = new BN(data.slice(i, Elen)) + i += Elen + var Mlen = data.length - i + var M = new BN(data.slice(i, Mlen)) + + console.log('MODEXP input', Blen, B, Elen, E, Mlen, M) + + result.gasUsed = new BN(Gmodexpbase).addi(Math.ceil(data.length / 32) * Garithword).addi(Blen * Mlen * Elen / Gquaddivisor) + + if (opts.gasLimit.cmp(results.gasUsed) === -1) { + results.gasUsed = opts.gasLimit + results.exception = 0 // 0 means VM fail (in this case because of OOG) + results.exceptionError = error.OUT_OF_GAS + return results + } + + // FIXME: use reduction contexts + var R = B.pow(E).mod(M).toArrayLike(Buffer, 'be') + var Rlen = new BN(R).toArrayLike(Buffer, 'be', 32) + + results.return = Buffer.concat(Rlen, R) + results.exception = 1 + + console.log('MODEXP output', Rlen, R) + + return results +}