class Ethereum::SpecialContract::ECRecover

Public Instance Methods

call(ext, msg) click to toggle source
# File lib/ethereum/special_contract.rb, line 6
def call(ext, msg)
  gas_cost = Opcodes::GECRECOVER
  return 0, 0, [] if msg.gas < gas_cost

  message_hash_ints = [0] * 32
  msg.data.extract_copy(message_hash_ints, 0, 0, 32)
  message_hash = Utils.int_array_to_bytes message_hash_ints

  v = msg.data.extract32(32)
  r = msg.data.extract32(64)
  s = msg.data.extract32(96)

  if r >= Secp256k1::N || s >= Secp256k1::N || v < 27 || v > 28
    return 1, msg.gas - gas_cost, []
  end

  signature_ints = [0] * 64
  msg.data.extract_copy signature_ints, 0, 64, 32  # r
  msg.data.extract_copy signature_ints, 32, 96, 32 # s
  signature = Utils.int_array_to_bytes signature_ints

  pub = nil
  begin
    pub = Secp256k1.recover_pubkey(message_hash, [v,r,s])
  rescue
    return 1, msg.gas - gas_cost, []
  end

  pubhash = Utils.keccak256(pub[1..-1])[-20..-1]
  o = Utils.bytes_to_int_array Utils.zpad(pubhash, 32)

  return 1, msg.gas - gas_cost, o
end