// Convert attempts to convert the constant x to a given type. // If the attempt is successful, the result is the new constant; // otherwise the result is invalid. func (x Const) Convert(typ *Type) Const { // TODO(gri) implement this switch x := x.Val.(type) { //case bool: case *big.Int: switch Underlying(*typ) { case Float32, Float64: var z big.Rat z.SetInt(x) return Const{&z} case String: return Const{string(x.Int64())} case Complex64, Complex128: var z big.Rat z.SetInt(x) return Const{Cmplx{&z, &big.Rat{}}} } case *big.Rat: switch Underlying(*typ) { case Byte, Int, Uint, Int8, Uint8, Int16, Uint16, Int32, Uint32, Int64, Uint64: // Convert to an integer. Remove the fractional component. num, denom := x.Num(), x.Denom() var z big.Int z.Quo(num, denom) return Const{&z} } //case Cmplx: //case string: } //panic("unimplemented") return x }
func (me *StatisticalAccumulator) PutInt(x *big.Int) { xx := new(big.Rat) xx.SetInt(x) me.PutRat(xx) }
// Float64 returns the numeric value of this literal truncated to fit // a float64. // func (l *Literal) Float64() float64 { switch x := l.Value.(type) { case int64: return float64(x) case *big.Int: var r big.Rat f, _ := r.SetInt(x).Float64() return f case *big.Rat: f, _ := x.Float64() return f } panic(fmt.Sprintf("unexpected literal value: %T", l.Value)) }
func main() { ln2, _ := new(big.Rat).SetString("0.6931471805599453094172") h := big.NewRat(1, 2) h.Quo(h, ln2) var f big.Rat var w big.Int for i := int64(1); i <= 17; i++ { h.Quo(h.Mul(h, f.SetInt64(i)), ln2) w.Quo(h.Num(), h.Denom()) f.Sub(h, f.SetInt(&w)) y, _ := f.Float64() d := fmt.Sprintf("%.3f", y) fmt.Printf("n: %2d h: %18d%s Nearly integer: %t\n", i, &w, d[1:], d[2] == '0' || d[2] == '9') } }
// Match attempts to match the internal constant representations of x and y. // If the attempt is successful, the result is the values of x and y, // if necessary converted to have the same internal representation; otherwise // the results are invalid. func (x Const) Match(y Const) (u, v Const) { switch a := x.val.(type) { case bool: if _, ok := y.val.(bool); ok { u, v = x, y } case *big.Int: switch y.val.(type) { case *big.Int: u, v = x, y case *big.Rat: var z big.Rat z.SetInt(a) u, v = Const{&z}, y case cmplx: var z big.Rat z.SetInt(a) u, v = Const{cmplx{&z, big.NewRat(0, 1)}}, y } case *big.Rat: switch y.val.(type) { case *big.Int: v, u = y.Match(x) case *big.Rat: u, v = x, y case cmplx: u, v = Const{cmplx{a, big.NewRat(0, 0)}}, y } case cmplx: switch y.val.(type) { case *big.Int, *big.Rat: v, u = y.Match(x) case cmplx: u, v = x, y } case string: if _, ok := y.val.(string); ok { u, v = x, y } default: panic("unreachable") } return }
//TODO collate1 should return errors instead of panicing func collate1(a, b interface{}) int { switch x := a.(type) { case nil: if b != nil { return -1 } return 0 case bool: switch y := b.(type) { case nil: return 1 case bool: if !x && y { return -1 } if x == y { return 0 } return 1 default: // Make bool collate before anything except nil and // other bool for index seeking first non NULL value. return -1 } case idealComplex: switch y := b.(type) { case nil: return 1 case idealComplex: if x == y { return 0 } if real(x) < real(y) { return -1 } if real(x) > real(y) { return 1 } if imag(x) < imag(y) { return -1 } return 1 case complex64: { x, y := complex64(x), complex64(y) if x == y { return 0 } if real(x) < real(y) { return -1 } if real(x) > real(y) { return 1 } if imag(x) < imag(y) { return -1 } return 1 } case complex128: { x := complex128(x) if x == y { return 0 } if real(x) < real(y) { return -1 } if real(x) > real(y) { return 1 } if imag(x) < imag(y) { return -1 } return 1 } default: panic("internal error 012") } case idealUint: switch y := b.(type) { case nil: return 1 case idealUint: if x < y { return -1 } if x == y { return 0 } return 1 case uint8: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case uint16: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case uint32: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case uint64: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case uint: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 013") } case idealRune: switch y := b.(type) { case nil: return 1 case idealRune: if x < y { return -1 } if x == y { return 0 } return 1 case int8: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case int16: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case int32: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case int64: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case int: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 014") } case idealInt: switch y := b.(type) { case nil: return 1 case idealInt: if x < y { return -1 } if x == y { return 0 } return 1 case int8: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case int16: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case int32: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case int64: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case int: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 015") } case idealFloat: switch y := b.(type) { case nil: return 1 case idealFloat: if x < y { return -1 } if x == y { return 0 } return 1 case float32: { x, y := float64(x), float64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case float64: { x, y := float64(x), float64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 016") } case complex64: switch y := b.(type) { case nil: return 1 case complex64: if x == y { return 0 } if real(x) < real(y) { return -1 } if real(x) > real(y) { return 1 } if imag(x) < imag(y) { return -1 } return 1 case idealComplex: { x, y := complex64(x), complex64(y) if x == y { return 0 } if real(x) < real(y) { return -1 } if real(x) > real(y) { return 1 } if imag(x) < imag(y) { return -1 } return 1 } default: panic("internal error 017") } case complex128: switch y := b.(type) { case nil: return 1 case complex128: if x == y { return 0 } if real(x) < real(y) { return -1 } if real(x) > real(y) { return 1 } if imag(x) < imag(y) { return -1 } return 1 case idealComplex: { x, y := complex128(x), complex128(y) if x == y { return 0 } if real(x) < real(y) { return -1 } if real(x) > real(y) { return 1 } if imag(x) < imag(y) { return -1 } return 1 } default: panic("internal error 018") } case float32: switch y := b.(type) { case nil: return 1 case float32: if x < y { return -1 } if x == y { return 0 } return 1 case idealFloat: { x, y := float32(x), float32(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 019") } case float64: switch y := b.(type) { case nil: return 1 case float64: if x < y { return -1 } if x == y { return 0 } return 1 case idealFloat: { x, y := float64(x), float64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 020") } case int8: switch y := b.(type) { case nil: return 1 case int8: if x < y { return -1 } if x == y { return 0 } return 1 case idealInt: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 021") } case int16: switch y := b.(type) { case nil: return 1 case int16: if x < y { return -1 } if x == y { return 0 } return 1 case idealInt: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 022") } case int32: switch y := b.(type) { case nil: return 1 case int32: if x < y { return -1 } if x == y { return 0 } return 1 case idealInt: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 023") } case int64: switch y := b.(type) { case nil: return 1 case int64: if x < y { return -1 } if x == y { return 0 } return 1 case idealInt: { x, y := int64(x), int64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: //dbg("%T(%#v)", b, b) panic("internal error 024") } case uint8: switch y := b.(type) { case nil: return 1 case uint8: if x < y { return -1 } if x == y { return 0 } return 1 case idealInt: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case idealUint: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 025") } case uint16: switch y := b.(type) { case nil: return 1 case uint16: if x < y { return -1 } if x == y { return 0 } return 1 case idealInt: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case idealUint: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 026") } case uint32: switch y := b.(type) { case nil: return 1 case uint32: if x < y { return -1 } if x == y { return 0 } return 1 case idealInt: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case idealUint: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 027") } case uint64: switch y := b.(type) { case nil: return 1 case uint64: if x < y { return -1 } if x == y { return 0 } return 1 case idealInt: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } case idealUint: { x, y := uint64(x), uint64(y) if x < y { return -1 } if x == y { return 0 } return 1 } default: panic("internal error 028") } case string: switch y := b.(type) { case nil: return 1 case string: if x < y { return -1 } if x == y { return 0 } return 1 default: panic("internal error 029") } case []byte: switch y := b.(type) { case nil: return 1 case []byte: return bytes.Compare(x, y) default: panic("internal error 030") } case *big.Int: switch y := b.(type) { case nil: return 1 case *big.Int: return x.Cmp(y) case idealInt: { y := big.NewInt(int64(y)) return x.Cmp(y) } case idealUint: { u := big.NewInt(0) u.SetUint64(uint64(y)) return x.Cmp(u) } default: panic("internal error 031") } case *big.Rat: switch y := b.(type) { case nil: return 1 case *big.Rat: return x.Cmp(y) case idealInt: { y := big.NewRat(int64(y), 1) return x.Cmp(y) } case idealUint: { u := big.NewInt(0) u.SetUint64(uint64(y)) var y big.Rat y.SetInt(u) return x.Cmp(&y) } default: panic("internal error 032") } case time.Time: switch y := b.(type) { case nil: return 1 case time.Time: if x.Before(y) { return -1 } if x.Equal(y) { return 0 } return 1 default: panic("internal error 033") } case time.Duration: switch y := b.(type) { case nil: return 1 case time.Duration: if x < y { return -1 } if x == y { return 0 } return 1 default: panic("internal error 034") } case chunk: switch y := b.(type) { case nil: return 1 case chunk: a, err := x.expand() if err != nil { log.Panic(err) } b, err := y.expand() if err != nil { log.Panic(err) } return collate1(a, b) default: panic("internal error 035") } default: panic("internal error 036") } }
func (vm *Vm) Process(contract *Contract, state *State, vars RuntimeVars) { vm.mem = make(map[string]*big.Int) vm.stack = NewStack() addr := vars.address // tx.Hash()[12:] // Instruction pointer pc := 0 if contract == nil { fmt.Println("Contract not found") return } Pow256 := ethutil.BigPow(2, 256) if ethutil.Config.Debug { ethutil.Config.Log.Debugf("# op\n") } stepcount := 0 totalFee := new(big.Int) out: for { stepcount++ // The base big int for all calculations. Use this for any results. base := new(big.Int) val := contract.GetMem(pc) //fmt.Printf("%x = %d, %v %x\n", r, len(r), v, nb) op := OpCode(val.Uint()) var fee *big.Int = new(big.Int) var fee2 *big.Int = new(big.Int) if stepcount > 16 { fee.Add(fee, StepFee) } // Calculate the fees switch op { case oSSTORE: y, x := vm.stack.Peekn() val := contract.Addr(ethutil.BigToBytes(x, 256)) if val.IsEmpty() && len(y.Bytes()) > 0 { fee2.Add(DataFee, StoreFee) } else { fee2.Sub(DataFee, StoreFee) } case oSLOAD: fee.Add(fee, StoreFee) case oEXTRO, oBALANCE: fee.Add(fee, ExtroFee) case oSHA256, oRIPEMD160, oECMUL, oECADD, oECSIGN, oECRECOVER, oECVALID: fee.Add(fee, CryptoFee) case oMKTX: fee.Add(fee, ContractFee) } tf := new(big.Int).Add(fee, fee2) if contract.Amount.Cmp(tf) < 0 { fmt.Println("Insufficient fees to continue running the contract", tf, contract.Amount) break } // Add the fee to the total fee. It's subtracted when we're done looping totalFee.Add(totalFee, tf) if ethutil.Config.Debug { ethutil.Config.Log.Debugf("%-3d %-4s", pc, op.String()) } switch op { case oSTOP: fmt.Println("") break out case oADD: x, y := vm.stack.Popn() // (x + y) % 2 ** 256 base.Add(x, y) base.Mod(base, Pow256) // Pop result back on the stack vm.stack.Push(base) case oSUB: x, y := vm.stack.Popn() // (x - y) % 2 ** 256 base.Sub(x, y) base.Mod(base, Pow256) // Pop result back on the stack vm.stack.Push(base) case oMUL: x, y := vm.stack.Popn() // (x * y) % 2 ** 256 base.Mul(x, y) base.Mod(base, Pow256) // Pop result back on the stack vm.stack.Push(base) case oDIV: x, y := vm.stack.Popn() // floor(x / y) base.Div(x, y) // Pop result back on the stack vm.stack.Push(base) case oSDIV: x, y := vm.stack.Popn() // n > 2**255 if x.Cmp(Pow256) > 0 { x.Sub(Pow256, x) } if y.Cmp(Pow256) > 0 { y.Sub(Pow256, y) } z := new(big.Int) z.Div(x, y) if z.Cmp(Pow256) > 0 { z.Sub(Pow256, z) } // Push result on to the stack vm.stack.Push(z) case oMOD: x, y := vm.stack.Popn() base.Mod(x, y) vm.stack.Push(base) case oSMOD: x, y := vm.stack.Popn() // n > 2**255 if x.Cmp(Pow256) > 0 { x.Sub(Pow256, x) } if y.Cmp(Pow256) > 0 { y.Sub(Pow256, y) } z := new(big.Int) z.Mod(x, y) if z.Cmp(Pow256) > 0 { z.Sub(Pow256, z) } // Push result on to the stack vm.stack.Push(z) case oEXP: x, y := vm.stack.Popn() base.Exp(x, y, Pow256) vm.stack.Push(base) case oNEG: base.Sub(Pow256, vm.stack.Pop()) vm.stack.Push(base) case oLT: x, y := vm.stack.Popn() // x < y if x.Cmp(y) < 0 { vm.stack.Push(ethutil.BigTrue) } else { vm.stack.Push(ethutil.BigFalse) } case oLE: x, y := vm.stack.Popn() // x <= y if x.Cmp(y) < 1 { vm.stack.Push(ethutil.BigTrue) } else { vm.stack.Push(ethutil.BigFalse) } case oGT: x, y := vm.stack.Popn() // x > y if x.Cmp(y) > 0 { vm.stack.Push(ethutil.BigTrue) } else { vm.stack.Push(ethutil.BigFalse) } case oGE: x, y := vm.stack.Popn() // x >= y if x.Cmp(y) > -1 { vm.stack.Push(ethutil.BigTrue) } else { vm.stack.Push(ethutil.BigFalse) } case oNOT: x, y := vm.stack.Popn() // x != y if x.Cmp(y) != 0 { vm.stack.Push(ethutil.BigTrue) } else { vm.stack.Push(ethutil.BigFalse) } case oMYADDRESS: vm.stack.Push(ethutil.BigD(addr)) case oTXSENDER: vm.stack.Push(ethutil.BigD(vars.sender)) case oTXVALUE: vm.stack.Push(vars.txValue) case oTXDATAN: vm.stack.Push(big.NewInt(int64(len(vars.txData)))) case oTXDATA: v := vm.stack.Pop() // v >= len(data) if v.Cmp(big.NewInt(int64(len(vars.txData)))) >= 0 { vm.stack.Push(ethutil.Big("0")) } else { vm.stack.Push(ethutil.Big(vars.txData[v.Uint64()])) } case oBLK_PREVHASH: vm.stack.Push(ethutil.BigD(vars.prevHash)) case oBLK_COINBASE: vm.stack.Push(ethutil.BigD(vars.coinbase)) case oBLK_TIMESTAMP: vm.stack.Push(big.NewInt(vars.time)) case oBLK_NUMBER: vm.stack.Push(big.NewInt(int64(vars.blockNumber))) case oBLK_DIFFICULTY: vm.stack.Push(vars.diff) case oBASEFEE: // e = 10^21 e := big.NewInt(0).Exp(big.NewInt(10), big.NewInt(21), big.NewInt(0)) d := new(big.Rat) d.SetInt(vars.diff) c := new(big.Rat) c.SetFloat64(0.5) // d = diff / 0.5 d.Quo(d, c) // base = floor(d) base.Div(d.Num(), d.Denom()) x := new(big.Int) x.Div(e, base) // x = floor(10^21 / floor(diff^0.5)) vm.stack.Push(x) case oSHA256, oSHA3, oRIPEMD160: // This is probably save // ceil(pop / 32) length := int(math.Ceil(float64(vm.stack.Pop().Uint64()) / 32.0)) // New buffer which will contain the concatenated popped items data := new(bytes.Buffer) for i := 0; i < length; i++ { // Encode the number to bytes and have it 32bytes long num := ethutil.NumberToBytes(vm.stack.Pop().Bytes(), 256) data.WriteString(string(num)) } if op == oSHA256 { vm.stack.Push(base.SetBytes(ethutil.Sha256Bin(data.Bytes()))) } else if op == oSHA3 { vm.stack.Push(base.SetBytes(ethutil.Sha3Bin(data.Bytes()))) } else { vm.stack.Push(base.SetBytes(ethutil.Ripemd160(data.Bytes()))) } case oECMUL: y := vm.stack.Pop() x := vm.stack.Pop() //n := vm.stack.Pop() //if ethutil.Big(x).Cmp(ethutil.Big(y)) { data := new(bytes.Buffer) data.WriteString(x.String()) data.WriteString(y.String()) if secp256k1.VerifyPubkeyValidity(data.Bytes()) == 1 { // TODO } else { // Invalid, push infinity vm.stack.Push(ethutil.Big("0")) vm.stack.Push(ethutil.Big("0")) } //} else { // // Invalid, push infinity // vm.stack.Push("0") // vm.stack.Push("0") //} case oECADD: case oECSIGN: case oECRECOVER: case oECVALID: case oPUSH: pc++ vm.stack.Push(contract.GetMem(pc).BigInt()) case oPOP: // Pop current value of the stack vm.stack.Pop() case oDUP: // Dup top stack x := vm.stack.Pop() vm.stack.Push(x) vm.stack.Push(x) case oSWAP: // Swap two top most values x, y := vm.stack.Popn() vm.stack.Push(y) vm.stack.Push(x) case oMLOAD: x := vm.stack.Pop() vm.stack.Push(vm.mem[x.String()]) case oMSTORE: x, y := vm.stack.Popn() vm.mem[x.String()] = y case oSLOAD: // Load the value in storage and push it on the stack x := vm.stack.Pop() // decode the object as a big integer decoder := contract.Addr(x.Bytes()) if !decoder.IsNil() { vm.stack.Push(decoder.BigInt()) } else { vm.stack.Push(ethutil.BigFalse) } case oSSTORE: // Store Y at index X y, x := vm.stack.Popn() addr := ethutil.BigToBytes(x, 256) fmt.Printf(" => %x (%v) @ %v", y.Bytes(), y, ethutil.BigD(addr)) contract.SetAddr(addr, y) //contract.State().Update(string(idx), string(y)) case oJMP: x := int(vm.stack.Pop().Uint64()) // Set pc to x - 1 (minus one so the incrementing at the end won't effect it) pc = x pc-- case oJMPI: x := vm.stack.Pop() // Set pc to x if it's non zero if x.Cmp(ethutil.BigFalse) != 0 { pc = int(x.Uint64()) pc-- } case oIND: vm.stack.Push(big.NewInt(int64(pc))) case oEXTRO: memAddr := vm.stack.Pop() contractAddr := vm.stack.Pop().Bytes() // Push the contract's memory on to the stack vm.stack.Push(contractMemory(state, contractAddr, memAddr)) case oBALANCE: // Pushes the balance of the popped value on to the stack account := state.GetAccount(vm.stack.Pop().Bytes()) vm.stack.Push(account.Amount) case oMKTX: addr, value := vm.stack.Popn() from, length := vm.stack.Popn() makeInlineTx(addr.Bytes(), value, from, length, contract, state) case oSUICIDE: recAddr := vm.stack.Pop().Bytes() // Purge all memory deletedMemory := contract.state.Purge() // Add refunds to the pop'ed address refund := new(big.Int).Mul(StoreFee, big.NewInt(int64(deletedMemory))) account := state.GetAccount(recAddr) account.Amount.Add(account.Amount, refund) // Update the refunding address state.UpdateAccount(recAddr, account) // Delete the contract state.trie.Update(string(addr), "") ethutil.Config.Log.Debugf("(%d) => %x\n", deletedMemory, recAddr) break out default: fmt.Printf("Invalid OPCODE: %x\n", op) } ethutil.Config.Log.Debugln("") //vm.stack.Print() pc++ } state.UpdateContract(addr, contract) }
// Contract evaluation is done here. func (bm *BlockManager) ProcContract(tx *ethutil.Transaction, block *ethutil.Block, cb TxCallback) { // Instruction pointer pc := 0 blockInfo := bm.BlockInfo(block) contract := block.GetContract(tx.Hash()) if contract == nil { fmt.Println("Contract not found") return } Pow256 := ethutil.BigPow(2, 256) //fmt.Printf("# op arg\n") out: for { // The base big int for all calculations. Use this for any results. base := new(big.Int) // XXX Should Instr return big int slice instead of string slice? // Get the next instruction from the contract //op, _, _ := Instr(contract.state.Get(string(Encode(uint32(pc))))) nb := ethutil.NumberToBytes(uint64(pc), 32) o, _, _ := ethutil.Instr(contract.State().Get(string(nb))) op := OpCode(o) if !cb(0) { break } if Debug { //fmt.Printf("%-3d %-4s\n", pc, op.String()) } switch op { case oSTOP: break out case oADD: x, y := bm.stack.Popn() // (x + y) % 2 ** 256 base.Add(x, y) base.Mod(base, Pow256) // Pop result back on the stack bm.stack.Push(base) case oSUB: x, y := bm.stack.Popn() // (x - y) % 2 ** 256 base.Sub(x, y) base.Mod(base, Pow256) // Pop result back on the stack bm.stack.Push(base) case oMUL: x, y := bm.stack.Popn() // (x * y) % 2 ** 256 base.Mul(x, y) base.Mod(base, Pow256) // Pop result back on the stack bm.stack.Push(base) case oDIV: x, y := bm.stack.Popn() // floor(x / y) base.Div(x, y) // Pop result back on the stack bm.stack.Push(base) case oSDIV: x, y := bm.stack.Popn() // n > 2**255 if x.Cmp(Pow256) > 0 { x.Sub(Pow256, x) } if y.Cmp(Pow256) > 0 { y.Sub(Pow256, y) } z := new(big.Int) z.Div(x, y) if z.Cmp(Pow256) > 0 { z.Sub(Pow256, z) } // Push result on to the stack bm.stack.Push(z) case oMOD: x, y := bm.stack.Popn() base.Mod(x, y) bm.stack.Push(base) case oSMOD: x, y := bm.stack.Popn() // n > 2**255 if x.Cmp(Pow256) > 0 { x.Sub(Pow256, x) } if y.Cmp(Pow256) > 0 { y.Sub(Pow256, y) } z := new(big.Int) z.Mod(x, y) if z.Cmp(Pow256) > 0 { z.Sub(Pow256, z) } // Push result on to the stack bm.stack.Push(z) case oEXP: x, y := bm.stack.Popn() base.Exp(x, y, Pow256) bm.stack.Push(base) case oNEG: base.Sub(Pow256, bm.stack.Pop()) bm.stack.Push(base) case oLT: x, y := bm.stack.Popn() // x < y if x.Cmp(y) < 0 { bm.stack.Push(ethutil.BigTrue) } else { bm.stack.Push(ethutil.BigFalse) } case oLE: x, y := bm.stack.Popn() // x <= y if x.Cmp(y) < 1 { bm.stack.Push(ethutil.BigTrue) } else { bm.stack.Push(ethutil.BigFalse) } case oGT: x, y := bm.stack.Popn() // x > y if x.Cmp(y) > 0 { bm.stack.Push(ethutil.BigTrue) } else { bm.stack.Push(ethutil.BigFalse) } case oGE: x, y := bm.stack.Popn() // x >= y if x.Cmp(y) > -1 { bm.stack.Push(ethutil.BigTrue) } else { bm.stack.Push(ethutil.BigFalse) } case oNOT: x, y := bm.stack.Popn() // x != y if x.Cmp(y) != 0 { bm.stack.Push(ethutil.BigTrue) } else { bm.stack.Push(ethutil.BigFalse) } // Please note that the following code contains some // ugly string casting. This will have to change to big // ints. TODO :) case oMYADDRESS: bm.stack.Push(ethutil.BigD(tx.Hash())) case oTXSENDER: bm.stack.Push(ethutil.BigD(tx.Sender())) case oTXVALUE: bm.stack.Push(tx.Value) case oTXDATAN: bm.stack.Push(big.NewInt(int64(len(tx.Data)))) case oTXDATA: v := bm.stack.Pop() // v >= len(data) if v.Cmp(big.NewInt(int64(len(tx.Data)))) >= 0 { bm.stack.Push(ethutil.Big("0")) } else { bm.stack.Push(ethutil.Big(tx.Data[v.Uint64()])) } case oBLK_PREVHASH: bm.stack.Push(ethutil.Big(block.PrevHash)) case oBLK_COINBASE: bm.stack.Push(ethutil.Big(block.Coinbase)) case oBLK_TIMESTAMP: bm.stack.Push(big.NewInt(block.Time)) case oBLK_NUMBER: bm.stack.Push(blockInfo.Number) case oBLK_DIFFICULTY: bm.stack.Push(block.Difficulty) case oBASEFEE: // e = 10^21 e := big.NewInt(0).Exp(big.NewInt(10), big.NewInt(21), big.NewInt(0)) d := new(big.Rat) d.SetInt(block.Difficulty) c := new(big.Rat) c.SetFloat64(0.5) // d = diff / 0.5 d.Quo(d, c) // base = floor(d) base.Div(d.Num(), d.Denom()) x := new(big.Int) x.Div(e, base) // x = floor(10^21 / floor(diff^0.5)) bm.stack.Push(x) case oSHA256, oSHA3, oRIPEMD160: // This is probably save // ceil(pop / 32) length := int(math.Ceil(float64(bm.stack.Pop().Uint64()) / 32.0)) // New buffer which will contain the concatenated popped items data := new(bytes.Buffer) for i := 0; i < length; i++ { // Encode the number to bytes and have it 32bytes long num := ethutil.NumberToBytes(bm.stack.Pop().Bytes(), 256) data.WriteString(string(num)) } if op == oSHA256 { bm.stack.Push(base.SetBytes(ethutil.Sha256Bin(data.Bytes()))) } else if op == oSHA3 { bm.stack.Push(base.SetBytes(ethutil.Sha3Bin(data.Bytes()))) } else { bm.stack.Push(base.SetBytes(ethutil.Ripemd160(data.Bytes()))) } case oECMUL: y := bm.stack.Pop() x := bm.stack.Pop() //n := bm.stack.Pop() //if ethutil.Big(x).Cmp(ethutil.Big(y)) { data := new(bytes.Buffer) data.WriteString(x.String()) data.WriteString(y.String()) if secp256k1.VerifyPubkeyValidity(data.Bytes()) == 1 { // TODO } else { // Invalid, push infinity bm.stack.Push(ethutil.Big("0")) bm.stack.Push(ethutil.Big("0")) } //} else { // // Invalid, push infinity // bm.stack.Push("0") // bm.stack.Push("0") //} case oECADD: case oECSIGN: case oECRECOVER: case oECVALID: case oPUSH: pc++ bm.stack.Push(bm.mem[strconv.Itoa(pc)]) case oPOP: // Pop current value of the stack bm.stack.Pop() case oDUP: // Dup top stack x := bm.stack.Pop() bm.stack.Push(x) bm.stack.Push(x) case oSWAP: // Swap two top most values x, y := bm.stack.Popn() bm.stack.Push(y) bm.stack.Push(x) case oMLOAD: x := bm.stack.Pop() bm.stack.Push(bm.mem[x.String()]) case oMSTORE: x, y := bm.stack.Popn() bm.mem[x.String()] = y case oSLOAD: // Load the value in storage and push it on the stack x := bm.stack.Pop() // decode the object as a big integer decoder := ethutil.NewRlpDecoder([]byte(contract.State().Get(x.String()))) if !decoder.IsNil() { bm.stack.Push(decoder.AsBigInt()) } else { bm.stack.Push(ethutil.BigFalse) } case oSSTORE: // Store Y at index X x, y := bm.stack.Popn() contract.State().Update(x.String(), string(ethutil.Encode(y))) case oJMP: x := int(bm.stack.Pop().Uint64()) // Set pc to x - 1 (minus one so the incrementing at the end won't effect it) pc = x pc-- case oJMPI: x := bm.stack.Pop() // Set pc to x if it's non zero if x.Cmp(ethutil.BigFalse) != 0 { pc = int(x.Uint64()) pc-- } case oIND: bm.stack.Push(big.NewInt(int64(pc))) case oEXTRO: memAddr := bm.stack.Pop() contractAddr := bm.stack.Pop().Bytes() // Push the contract's memory on to the stack bm.stack.Push(getContractMemory(block, contractAddr, memAddr)) case oBALANCE: // Pushes the balance of the popped value on to the stack d := block.State().Get(bm.stack.Pop().String()) ether := ethutil.NewEtherFromData([]byte(d)) bm.stack.Push(ether.Amount) case oMKTX: value, addr := bm.stack.Popn() from, length := bm.stack.Popn() j := 0 dataItems := make([]string, int(length.Uint64())) for i := from.Uint64(); i < length.Uint64(); i++ { dataItems[j] = string(bm.mem[strconv.Itoa(int(i))].Bytes()) j++ } // TODO sign it? tx := ethutil.NewTransaction(string(addr.Bytes()), value, dataItems) // Add the transaction to the tx pool bm.server.txPool.QueueTransaction(tx) case oSUICIDE: //addr := bm.stack.Pop() } pc++ } bm.stack.Print() }