|  | 
|  | 1 | +/*  | 
|  | 2 | +At the address 0x0000....09, add a precompile that expects input in the following format: | 
|  | 3 | +
 | 
|  | 4 | +<length of B, as a 32-byte-padded integer> <bytes of B> <length of E, as a 32-byte-padded integer> <bytes of E> <bytes of M> | 
|  | 5 | +
 | 
|  | 6 | +This should return B**E % M, and the data should be returned in the same format as above. If M = 0, it returns zero. Gas cost GMODEXPBASE + GARITHWORD * ceil(<total length of input data> / 32) + <length of M> * <length of M> * <length of E> / GQUADDIVISOR. | 
|  | 7 | + * | 
|  | 8 | + */ | 
|  | 9 | + | 
|  | 10 | +const utils = require('ethereumjs-util') | 
|  | 11 | +const BN = utils.BN | 
|  | 12 | +const error = require('../constants.js').ERROR | 
|  | 13 | + | 
|  | 14 | +const Gmodexpbase = 45 | 
|  | 15 | +const Garithword = 6 | 
|  | 16 | +const Gquaddivisor = 32 | 
|  | 17 | + | 
|  | 18 | +module.exports = function (opts) { | 
|  | 19 | +  var results = {} | 
|  | 20 | + | 
|  | 21 | +  var i = 0 | 
|  | 22 | +  var Blen = new BN(data.slice(i, 32)).toNumber() | 
|  | 23 | +  i += 32 | 
|  | 24 | +  var B = new BN(data.slice(i, i + Blen)) | 
|  | 25 | +  i += Blen | 
|  | 26 | +  var Elen = new BN(data.slice(i, i + 32)).toNumber() | 
|  | 27 | +  i += 32 | 
|  | 28 | +  var E = new BN(data.slice(i, Elen)) | 
|  | 29 | +  i += Elen | 
|  | 30 | +  var Mlen = data.length - i | 
|  | 31 | +  var M = new BN(data.slice(i, Mlen)) | 
|  | 32 | +   | 
|  | 33 | +  console.log('MODEXP input', Blen, B, Elen, E, Mlen, M) | 
|  | 34 | + | 
|  | 35 | +  result.gasUsed = new BN(Gmodexpbase).addi(Math.ceil(data.length / 32) * Garithword).addi(Blen * Mlen * Elen / Gquaddivisor) | 
|  | 36 | + | 
|  | 37 | +  if (opts.gasLimit.cmp(results.gasUsed) === -1) { | 
|  | 38 | +    results.gasUsed = opts.gasLimit | 
|  | 39 | +    results.exception = 0 // 0 means VM fail (in this case because of OOG) | 
|  | 40 | +    results.exceptionError = error.OUT_OF_GAS | 
|  | 41 | +    return results | 
|  | 42 | +  } | 
|  | 43 | + | 
|  | 44 | +  // FIXME: use reduction contexts | 
|  | 45 | +  var R = B.pow(E).mod(M).toArrayLike(Buffer, 'be') | 
|  | 46 | +  var Rlen = new BN(R).toArrayLike(Buffer, 'be', 32) | 
|  | 47 | + | 
|  | 48 | +  results.return = Buffer.concat(Rlen, R) | 
|  | 49 | +  results.exception = 1 | 
|  | 50 | + | 
|  | 51 | +  console.log('MODEXP output', Rlen, R) | 
|  | 52 | + | 
|  | 53 | +  return results | 
|  | 54 | +} | 
0 commit comments