Commit ede82663 authored by George Hotz's avatar George Hotz

minigeth emulation is real

parent 628f5b90
...@@ -17,11 +17,22 @@ interface IMIPSMemory { ...@@ -17,11 +17,22 @@ interface IMIPSMemory {
} }
contract MIPS { contract MIPS {
IMIPSMemory constant public m = IMIPSMemory(0x1338); IMIPSMemory public immutable m;
uint32 constant public REG_OFFSET = 0xc0000000; uint32 constant public REG_OFFSET = 0xc0000000;
uint32 constant public REG_PC = REG_OFFSET + 0x20*4; uint32 constant public REG_PC = REG_OFFSET + 0x20*4;
constructor(IMIPSMemory _m) {
m = _m;
}
function Steps(bytes32 stateHash, uint count) public view returns (bytes32) {
for (uint i = 0; i < count; i++) {
stateHash = Step(stateHash);
}
return stateHash;
}
// will revert if any required input state is missing // will revert if any required input state is missing
function Step(bytes32 stateHash) public view returns (bytes32) { function Step(bytes32 stateHash) public view returns (bytes32) {
// instruction fetch // instruction fetch
......
...@@ -2,5 +2,13 @@ ...@@ -2,5 +2,13 @@
* @type import('hardhat/config').HardhatUserConfig * @type import('hardhat/config').HardhatUserConfig
*/ */
module.exports = { module.exports = {
solidity: "0.7.3", solidity: {
version: "0.7.3",
settings: {
optimizer: {
enabled: true,
runs: 200
}
}
},
}; };
...@@ -137,6 +137,10 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter { ...@@ -137,6 +137,10 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter {
} }
} }
func (in *EVMInterpreter) GetCfg() *Config {
return &in.cfg
}
// Run loops and evaluates the contract's code with the given input data and returns // Run loops and evaluates the contract's code with the given input data and returns
// the return byte-slice and an error if one occurred. // the return byte-slice and an error if one occurred.
// //
......
...@@ -48,6 +48,10 @@ type operation struct { ...@@ -48,6 +48,10 @@ type operation struct {
returns bool // determines whether the operations sets the return data content returns bool // determines whether the operations sets the return data content
} }
func (o *operation) SetExecute(f executionFunc) {
o.execute = f
}
var ( var (
frontierInstructionSet = newFrontierInstructionSet() frontierInstructionSet = newFrontierInstructionSet()
homesteadInstructionSet = newHomesteadInstructionSet() homesteadInstructionSet = newHomesteadInstructionSet()
......
...@@ -50,6 +50,11 @@ func (st *Stack) Data() []uint256.Int { ...@@ -50,6 +50,11 @@ func (st *Stack) Data() []uint256.Int {
return st.data return st.data
} }
func (st *Stack) Push(d *uint256.Int) {
// NOTE push limit (1024) is checked in baseCheck
st.data = append(st.data, *d)
}
func (st *Stack) push(d *uint256.Int) { func (st *Stack) push(d *uint256.Int) {
// NOTE push limit (1024) is checked in baseCheck // NOTE push limit (1024) is checked in baseCheck
st.data = append(st.data, *d) st.data = append(st.data, *d)
...@@ -59,6 +64,12 @@ func (st *Stack) pushN(ds ...uint256.Int) { ...@@ -59,6 +64,12 @@ func (st *Stack) pushN(ds ...uint256.Int) {
st.data = append(st.data, ds...) st.data = append(st.data, ds...)
} }
func (st *Stack) Pop() (ret uint256.Int) {
ret = st.data[len(st.data)-1]
st.data = st.data[:len(st.data)-1]
return
}
func (st *Stack) pop() (ret uint256.Int) { func (st *Stack) pop() (ret uint256.Int) {
ret = st.data[len(st.data)-1] ret = st.data[len(st.data)-1]
st.data = st.data[:len(st.data)-1] st.data = st.data[:len(st.data)-1]
......
...@@ -40,7 +40,7 @@ func (s *StateDB) GetCode(addr common.Address) []byte { ...@@ -40,7 +40,7 @@ func (s *StateDB) GetCode(addr common.Address) []byte {
return s.Bytecode return s.Bytecode
} }
func (s *StateDB) GetCodeHash(addr common.Address) common.Hash { return common.Hash{} } func (s *StateDB) GetCodeHash(addr common.Address) common.Hash { return common.Hash{} }
func (s *StateDB) GetCodeSize(addr common.Address) int { return 0 } func (s *StateDB) GetCodeSize(addr common.Address) int { return 100 }
func (s *StateDB) GetCommittedState(addr common.Address, hash common.Hash) common.Hash { func (s *StateDB) GetCommittedState(addr common.Address, hash common.Hash) common.Hash {
return common.Hash{} return common.Hash{}
} }
...@@ -74,7 +74,7 @@ func (jst *Tracer) CaptureStart(env *vm.EVM, from common.Address, to common.Addr ...@@ -74,7 +74,7 @@ func (jst *Tracer) CaptureStart(env *vm.EVM, from common.Address, to common.Addr
// CaptureState implements the Tracer interface to trace a single step of VM execution. // CaptureState implements the Tracer interface to trace a single step of VM execution.
func (jst *Tracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) { func (jst *Tracer) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
fmt.Println(pc, op, gas) //fmt.Println(pc, op, gas)
} }
// CaptureFault implements the Tracer interface to trace an execution fault // CaptureFault implements the Tracer interface to trace an execution fault
...@@ -90,6 +90,33 @@ type jsoncontract struct { ...@@ -90,6 +90,33 @@ type jsoncontract struct {
DeployedBytecode string `json:"deployedBytecode"` DeployedBytecode string `json:"deployedBytecode"`
} }
func opStaticCall(pc *uint64, interpreter *vm.EVMInterpreter, scope *vm.ScopeContext) ([]byte, error) {
// Pop gas. The actual gas is in interpreter.evm.callGasTemp.
stack := scope.Stack
temp := stack.Pop()
returnGas := temp.Uint64()
_, inOffset, inSize, retOffset, retSize := stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop(), stack.Pop()
//fmt.Println(temp, addr, inOffset, inSize, retOffset, retSize)
temp.SetOne()
stack.Push(&temp)
ret := common.Hash{}.Bytes()
// Get arguments from the memory.
args := scope.Memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64()))
//scope.Memory.GetPtr(int64(inOffset.Uint64()), int64(inSize.Uint64()))
fmt.Println("HOOKED!", returnGas, args)
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
//scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
//return ret
scope.Contract.Gas += returnGas
return ret, nil
}
func main() { func main() {
fmt.Println("hello") fmt.Println("hello")
...@@ -125,13 +152,27 @@ func main() { ...@@ -125,13 +152,27 @@ func main() {
fmt.Println(ret, gas, err)*/ fmt.Println(ret, gas, err)*/
interpreter := vm.NewEVMInterpreter(evm, config) interpreter := vm.NewEVMInterpreter(evm, config)
input := []byte{0x69, 0x37, 0x33, 0x72} // Step(bytes32) interpreter.GetCfg().JumpTable[vm.STATICCALL].SetExecute(opStaticCall)
/*input := []byte{0x69, 0x37, 0x33, 0x72} // Step(bytes32)
input = append(input, common.Hash{}.Bytes()...)*/
// 1.26s for 100000 steps
steps := 10
// 0xdb7df598
input := []byte{0xdb, 0x7d, 0xf5, 0x98} // Steps(bytes32, uint256)
input = append(input, common.Hash{}.Bytes()...) input = append(input, common.Hash{}.Bytes()...)
input = append(input, common.BigToHash(big.NewInt(int64(steps))).Bytes()...)
contract := vm.NewContract(vm.AccountRef(from), vm.AccountRef(to), common.Big0, 20000000) contract := vm.NewContract(vm.AccountRef(from), vm.AccountRef(to), common.Big0, 20000000)
//fmt.Println(bytecodehash, bytecode) //fmt.Println(bytecodehash, bytecode)
contract.SetCallCode(&to, bytecodehash, bytecode) contract.SetCallCode(&to, bytecodehash, bytecode)
start := time.Now()
ret, err := interpreter.Run(contract, input, false) ret, err := interpreter.Run(contract, input, false)
fmt.Println(ret, err, contract.Gas) elapsed := time.Now().Sub(start)
fmt.Println(ret, err, contract.Gas, elapsed)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment