func ratProb(mode int) func(*big.Rat) *big.Rat { return func(x *big.Rat) *big.Rat { lo := big.NewInt(0) hi := new(big.Int).Set(big2p63) n := 0 for lo.Cmp(hi) != 0 { m := new(big.Int).Add(lo, hi) m = m.Rsh(m, 1) if n++; n > 100 { fmt.Printf("??? %v %v %v\n", lo, hi, m) break } v := new(big.Rat).SetFrac(m, big2p63) f, _ := v.Float64() v.SetFloat64(f) if v.Cmp(x) < 0 { lo.Add(m, bigOne) } else { hi.Set(m) } } switch mode { default: // case 0 return new(big.Rat).SetFrac(lo, big2p63) case 1: if lo.Cmp(big.NewInt(cutoff1)) <= 0 { lo.Add(lo, big.NewInt(1<<63-cutoff1)) } return new(big.Rat).SetFrac(lo, big2p63) case 2: return new(big.Rat).SetFrac(lo, big.NewInt(cutoff1)) } } }
func getBalance(balance string) (bool, *big.Rat) { rationalNum := new(big.Rat) if strings.Contains(balance, "(") { rationalNum.SetFloat64(calc.Solve(balance)) return true, rationalNum } _, isValid := rationalNum.SetString(balance) return isValid, rationalNum }
//export OFXTransactionCallback func OFXTransactionCallback(transaction_data C.struct_OfxTransactionData, data unsafe.Pointer) C.int { iobj := (*ImportObject)(data) itl := iobj.TransactionList transaction := new(Transaction) if transaction_data.name_valid != 0 { transaction.Description = C.GoString(&transaction_data.name[0]) } // if transaction_data.reference_number_valid != 0 { // fmt.Println("reference_number: ", C.GoString(&transaction_data.reference_number[0])) // } if transaction_data.date_posted_valid != 0 { transaction.Date = time.Unix(int64(transaction_data.date_posted), 0) } else if transaction_data.date_initiated_valid != 0 { transaction.Date = time.Unix(int64(transaction_data.date_initiated), 0) } if transaction_data.fi_id_valid != 0 { transaction.RemoteId = C.GoString(&transaction_data.fi_id[0]) } if transaction_data.amount_valid != 0 { split := new(Split) r := new(big.Rat) r.SetFloat64(float64(transaction_data.amount)) security, err := GetSecurity(itl.Account.SecurityId, itl.Account.UserId) if err != nil { if iobj.Error == nil { iobj.Error = err } return 1 } split.Amount = r.FloatString(security.Precision) if transaction_data.memo_valid != 0 { split.Memo = C.GoString(&transaction_data.memo[0]) } if transaction_data.check_number_valid != 0 { split.Number = C.GoString(&transaction_data.check_number[0]) } split.SecurityId = -1 split.AccountId = itl.Account.AccountId transaction.Splits = append(transaction.Splits, split) } else { if iobj.Error == nil { iobj.Error = errors.New("OFX transaction amount invalid") } return 1 } var security *Security var err error split := new(Split) units := new(big.Rat) if transaction_data.units_valid != 0 { units.SetFloat64(float64(transaction_data.units)) if transaction_data.security_data_valid != 0 { security_data := transaction_data.security_data_ptr if security_data.ticker_valid != 0 { s, err := GetSecurityByName(C.GoString(&security_data.ticker[0])) if err != nil { if iobj.Error == nil { iobj.Error = errors.New("Failed to find OFX transaction security: " + C.GoString(&security_data.ticker[0])) } return 1 } security = s } else { if iobj.Error == nil { iobj.Error = errors.New("OFX security ticker invalid") } return 1 } if security.Type == Stock && security_data.unique_id_valid != 0 && security_data.unique_id_type_valid != 0 && C.GoString(&security_data.unique_id_type[0]) == "CUSIP" { // Validate the security CUSIP, if possible if security.AlternateId != C.GoString(&security_data.unique_id[0]) { if iobj.Error == nil { iobj.Error = errors.New("OFX transaction security CUSIP failed to validate") } return 1 } } } else { security, err = GetSecurity(itl.Account.SecurityId, itl.Account.UserId) if err != nil { if iobj.Error == nil { iobj.Error = err } return 1 } } } else { // Calculate units from other available fields if its not present // units = - (amount + various fees) / unitprice units.SetFloat64(float64(transaction_data.amount)) fees := new(big.Rat) if transaction_data.fees_valid != 0 { fees.SetFloat64(float64(-transaction_data.fees)) } if transaction_data.commission_valid != 0 { commission := new(big.Rat) commission.SetFloat64(float64(-transaction_data.commission)) fees.Add(fees, commission) } units.Add(units, fees) units.Neg(units) if transaction_data.unitprice_valid != 0 && transaction_data.unitprice != 0 { unitprice := new(big.Rat) unitprice.SetFloat64(float64(transaction_data.unitprice)) units.Quo(units, unitprice) } // If 'units' wasn't present, assume we're using the account's security security, err = GetSecurity(itl.Account.SecurityId, itl.Account.UserId) if err != nil { if iobj.Error == nil { iobj.Error = err } return 1 } } split.Amount = units.FloatString(security.Precision) split.SecurityId = security.SecurityId split.AccountId = -1 transaction.Splits = append(transaction.Splits, split) if transaction_data.fees_valid != 0 { split := new(Split) r := new(big.Rat) r.SetFloat64(float64(-transaction_data.fees)) security, err := GetSecurity(itl.Account.SecurityId, itl.Account.UserId) if err != nil { if iobj.Error == nil { iobj.Error = err } return 1 } split.Amount = r.FloatString(security.Precision) split.Memo = "fees" split.SecurityId = itl.Account.SecurityId split.AccountId = -1 transaction.Splits = append(transaction.Splits, split) } if transaction_data.commission_valid != 0 { split := new(Split) r := new(big.Rat) r.SetFloat64(float64(-transaction_data.commission)) security, err := GetSecurity(itl.Account.SecurityId, itl.Account.UserId) if err != nil { if iobj.Error == nil { iobj.Error = err } return 1 } split.Amount = r.FloatString(security.Precision) split.Memo = "commission" split.SecurityId = itl.Account.SecurityId split.AccountId = -1 transaction.Splits = append(transaction.Splits, split) } // if transaction_data.payee_id_valid != 0 { // fmt.Println("payee_id: ", C.GoString(&transaction_data.payee_id[0])) // } transaction_list := append(*itl.Transactions, *transaction) iobj.TransactionList.Transactions = &transaction_list return 0 }
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) }
func FloatToRat(v float64) *big.Rat { rat := new(big.Rat) rat.SetFloat64(v) return rat }
// 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() }