func (self *XEth) PushTx(encodedTx string) (string, error) { tx := new(types.Transaction) err := rlp.DecodeBytes(common.FromHex(encodedTx), tx) if err != nil { glog.V(logger.Error).Infoln(err) return "", err } err = self.backend.TxPool().Add(tx) if err != nil { return "", err } if tx.To() == nil { from, err := tx.From() if err != nil { return "", err } addr := crypto.CreateAddress(from, tx.Nonce()) glog.V(logger.Info).Infof("Tx(%x) created: %x\n", tx.Hash(), addr) } else { glog.V(logger.Info).Infof("Tx(%x) to: %x\n", tx.Hash(), tx.To()) } return tx.Hash().Hex(), nil }
func NewTx(tx *types.Transaction) *Transaction { sender, err := tx.From() if err != nil { return nil } hash := tx.Hash().Hex() var receiver string if to := tx.To(); to != nil { receiver = to.Hex() } else { from, _ := tx.From() receiver = crypto.CreateAddress(from, tx.Nonce()).Hex() } createsContract := core.MessageCreatesContract(tx) var data string if createsContract { data = strings.Join(core.Disassemble(tx.Data()), "\n") } else { data = common.ToHex(tx.Data()) } return &Transaction{ref: tx, Hash: hash, Value: common.CurrencyToString(tx.Value()), Address: receiver, Contract: createsContract, Gas: tx.Gas().String(), GasPrice: tx.GasPrice().String(), Data: data, Sender: sender.Hex(), CreatesContract: createsContract, RawData: common.ToHex(tx.Data())} }
func (self *BlockProcessor) ApplyTransaction(gp GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, transientProcess bool) (*types.Receipt, *big.Int, error) { _, gas, err := ApplyMessage(NewEnv(statedb, self.bc, tx, header), tx, gp) if err != nil { return nil, nil, err } // Update the state with pending changes statedb.SyncIntermediate() usedGas.Add(usedGas, gas) receipt := types.NewReceipt(statedb.Root().Bytes(), usedGas) receipt.TxHash = tx.Hash() receipt.GasUsed = new(big.Int).Set(gas) if MessageCreatesContract(tx) { from, _ := tx.From() receipt.ContractAddress = crypto.CreateAddress(from, tx.Nonce()) } logs := statedb.GetLogs(tx.Hash()) receipt.SetLogs(logs) receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) glog.V(logger.Debug).Infoln(receipt) // Notify all subscribers if !transientProcess { go self.eventMux.Post(TxPostEvent{tx}) go self.eventMux.Post(logs) } return receipt, gas, err }
func (self *Env) Create(caller vm.ContractRef, data []byte, gas, price, value *big.Int) ([]byte, common.Address, error) { if self.vmTest { caller.ReturnGas(gas, price) nonce := self.state.GetNonce(caller.Address()) obj := self.state.GetOrNewStateObject(crypto.CreateAddress(caller.Address(), nonce)) return nil, obj.Address(), nil } else { return core.Create(self, caller, data, gas, price, value) } }
func (self *Env) Create(caller vm.ContextRef, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) { exe := self.vm(nil, data, gas, price, value) if self.vmTest { caller.ReturnGas(gas, price) nonce := self.state.GetNonce(caller.Address()) obj := self.state.GetOrNewStateObject(crypto.CreateAddress(caller.Address(), nonce)) return nil, nil, obj } else { return exe.Create(caller) } }
// exec executes the given code and executes within the contextAddr context. func (self *Execution) exec(contextAddr *common.Address, code []byte, caller vm.ContextRef) (ret []byte, err error) { env := self.env evm := self.evm // Depth check execution. Fail if we're trying to execute above the // limit. if env.Depth() > int(params.CallCreateDepth.Int64()) { caller.ReturnGas(self.Gas, self.price) return nil, vm.DepthError } if !env.CanTransfer(env.State().GetStateObject(caller.Address()), self.value) { caller.ReturnGas(self.Gas, self.price) return nil, ValueTransferErr("insufficient funds to transfer value. Req %v, has %v", self.value, env.State().GetBalance(caller.Address())) } var createAccount bool if self.address == nil { // Generate a new address nonce := env.State().GetNonce(caller.Address()) env.State().SetNonce(caller.Address(), nonce+1) addr := crypto.CreateAddress(caller.Address(), nonce) self.address = &addr createAccount = true } snapshot := env.State().Copy() var ( from = env.State().GetStateObject(caller.Address()) to *state.StateObject ) if createAccount { to = env.State().CreateAccount(*self.address) } else { to = env.State().GetOrNewStateObject(*self.address) } vm.Transfer(from, to, self.value) context := vm.NewContext(caller, to, self.value, self.Gas, self.price) context.SetCallCode(contextAddr, code) ret, err = evm.Run(context, self.input) if err != nil { env.State().Set(snapshot) } return }
// DeployContract deploys a contract onto the Expanse blockchain and binds the // deployment address with a Go wrapper. func DeployContract(opts *TransactOpts, abi abi.ABI, bytecode []byte, backend ContractBackend, params ...interface{}) (common.Address, *types.Transaction, *BoundContract, error) { // Otherwise try to deploy the contract c := NewBoundContract(common.Address{}, abi, backend, backend) input, err := c.abi.Pack("", params...) if err != nil { return common.Address{}, nil, nil, err } tx, err := c.transact(opts, nil, append(bytecode, input...)) if err != nil { return common.Address{}, nil, nil, err } c.address = crypto.CreateAddress(opts.From, tx.Nonce()) return c.address, tx, c, nil }
// ApplyTransaction attemps to apply a transaction to the given state database // and uses the input parameters for its environment. // // ApplyTransactions returns the generated receipts and vm logs during the // execution of the state transition phase. func ApplyTransaction(bc *BlockChain, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int) (*types.Receipt, vm.Logs, *big.Int, error) { _, gas, err := ApplyMessage(NewEnv(statedb, bc, tx, header), tx, gp) if err != nil { return nil, nil, nil, err } // Update the state with pending changes usedGas.Add(usedGas, gas) receipt := types.NewReceipt(statedb.IntermediateRoot().Bytes(), usedGas) receipt.TxHash = tx.Hash() receipt.GasUsed = new(big.Int).Set(gas) if MessageCreatesContract(tx) { from, _ := tx.From() receipt.ContractAddress = crypto.CreateAddress(from, tx.Nonce()) } logs := statedb.GetLogs(tx.Hash()) receipt.Logs = logs receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) glog.V(logger.Debug).Infoln(receipt) return receipt, logs, gas, err }
// InsertReceiptChain attempts to complete an already existing header chain with // transaction and receipt data. func (self *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) { self.wg.Add(1) defer self.wg.Done() // Collect some import statistics to report on stats := struct{ processed, ignored int32 }{} start := time.Now() // Create the block importing task queue and worker functions tasks := make(chan int, len(blockChain)) for i := 0; i < len(blockChain) && i < len(receiptChain); i++ { tasks <- i } close(tasks) errs, failed := make([]error, len(tasks)), int32(0) process := func(worker int) { for index := range tasks { block, receipts := blockChain[index], receiptChain[index] // Short circuit insertion if shutting down or processing failed if atomic.LoadInt32(&self.procInterrupt) == 1 { return } if atomic.LoadInt32(&failed) > 0 { return } // Short circuit if the owner header is unknown if !self.HasHeader(block.Hash()) { errs[index] = fmt.Errorf("containing header #%d [%x…] unknown", block.Number(), block.Hash().Bytes()[:4]) atomic.AddInt32(&failed, 1) return } // Skip if the entire data is already known if self.HasBlock(block.Hash()) { atomic.AddInt32(&stats.ignored, 1) continue } // Compute all the non-consensus fields of the receipts transactions, logIndex := block.Transactions(), uint(0) for j := 0; j < len(receipts); j++ { // The transaction hash can be retrieved from the transaction itself receipts[j].TxHash = transactions[j].Hash() // The contract address can be derived from the transaction itself if MessageCreatesContract(transactions[j]) { from, _ := transactions[j].From() receipts[j].ContractAddress = crypto.CreateAddress(from, transactions[j].Nonce()) } // The used gas can be calculated based on previous receipts if j == 0 { receipts[j].GasUsed = new(big.Int).Set(receipts[j].CumulativeGasUsed) } else { receipts[j].GasUsed = new(big.Int).Sub(receipts[j].CumulativeGasUsed, receipts[j-1].CumulativeGasUsed) } // The derived log fields can simply be set from the block and transaction for k := 0; k < len(receipts[j].Logs); k++ { receipts[j].Logs[k].BlockNumber = block.NumberU64() receipts[j].Logs[k].BlockHash = block.Hash() receipts[j].Logs[k].TxHash = receipts[j].TxHash receipts[j].Logs[k].TxIndex = uint(j) receipts[j].Logs[k].Index = logIndex logIndex++ } } // Write all the data out into the database if err := WriteBody(self.chainDb, block.Hash(), &types.Body{block.Transactions(), block.Uncles()}); err != nil { errs[index] = fmt.Errorf("failed to write block body: %v", err) atomic.AddInt32(&failed, 1) glog.Fatal(errs[index]) return } if err := WriteBlockReceipts(self.chainDb, block.Hash(), receipts); err != nil { errs[index] = fmt.Errorf("failed to write block receipts: %v", err) atomic.AddInt32(&failed, 1) glog.Fatal(errs[index]) return } if err := WriteMipmapBloom(self.chainDb, block.NumberU64(), receipts); err != nil { errs[index] = fmt.Errorf("failed to write log blooms: %v", err) atomic.AddInt32(&failed, 1) glog.Fatal(errs[index]) return } atomic.AddInt32(&stats.processed, 1) } } // Start as many worker threads as goroutines allowed pending := new(sync.WaitGroup) for i := 0; i < runtime.GOMAXPROCS(0); i++ { pending.Add(1) go func(id int) { defer pending.Done() process(id) }(i) } pending.Wait() // If anything failed, report if failed > 0 { for i, err := range errs { if err != nil { return i, err } } } if atomic.LoadInt32(&self.procInterrupt) == 1 { glog.V(logger.Debug).Infoln("premature abort during receipt chain processing") return 0, nil } // Update the head fast sync block if better self.mu.Lock() head := blockChain[len(errs)-1] if self.GetTd(self.currentFastBlock.Hash()).Cmp(self.GetTd(head.Hash())) < 0 { if err := WriteHeadFastBlockHash(self.chainDb, head.Hash()); err != nil { glog.Fatalf("failed to update head fast block hash: %v", err) } self.currentFastBlock = head } self.mu.Unlock() // Report some public statistics so the user has a clue what's going on first, last := blockChain[0], blockChain[len(blockChain)-1] glog.V(logger.Info).Infof("imported %d receipt(s) (%d ignored) in %v. #%d [%x… / %x…]", stats.processed, stats.ignored, time.Since(start), last.Number(), first.Hash().Bytes()[:4], last.Hash().Bytes()[:4]) return 0, nil }
func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.Address, codeHash common.Hash, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) { evm := env.Vm() // Depth check execution. Fail if we're trying to execute above the // limit. if env.Depth() > int(params.CallCreateDepth.Int64()) { caller.ReturnGas(gas, gasPrice) return nil, common.Address{}, vm.DepthError } if !env.CanTransfer(caller.Address(), value) { caller.ReturnGas(gas, gasPrice) return nil, common.Address{}, ValueTransferErr("insufficient funds to transfer value. Req %v, has %v", value, env.Db().GetBalance(caller.Address())) } var createAccount bool if address == nil { // Create a new account on the state nonce := env.Db().GetNonce(caller.Address()) env.Db().SetNonce(caller.Address(), nonce+1) addr = crypto.CreateAddress(caller.Address(), nonce) address = &addr createAccount = true } snapshotPreTransfer := env.SnapshotDatabase() var ( from = env.Db().GetAccount(caller.Address()) to vm.Account ) if createAccount { to = env.Db().CreateAccount(*address) } else { if !env.Db().Exist(*address) { to = env.Db().CreateAccount(*address) } else { to = env.Db().GetAccount(*address) } } env.Transfer(from, to, value) // initialise a new contract and set the code that is to be used by the // EVM. The contract is a scoped environment for this execution context // only. contract := vm.NewContract(caller, to, value, gas, gasPrice) contract.SetCallCode(codeAddr, codeHash, code) defer contract.Finalise() ret, err = evm.Run(contract, input) // if the contract creation ran successfully and no errors were returned // calculate the gas required to store the code. If the code could not // be stored due to not enough gas set an error and let it be handled // by the error checking condition below. if err == nil && createAccount { dataGas := big.NewInt(int64(len(ret))) dataGas.Mul(dataGas, params.CreateDataGas) if contract.UseGas(dataGas) { env.Db().SetCode(*address, ret) } else { err = vm.CodeStoreOutOfGasError } } // When an error was returned by the EVM or when setting the creation code // above we revert to the snapshot and consume any gas remaining. Additionally // when we're in homestead this also counts for code storage gas errors. if err != nil && (env.RuleSet().IsHomestead(env.BlockNumber()) || err != vm.CodeStoreOutOfGasError) { contract.UseGas(contract.Gas) env.RevertToSnapshot(snapshotPreTransfer) } return ret, addr, err }
func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) { // this minimalistic recoding is enough (works for natspec.js) var jsontx = fmt.Sprintf(`{"params":[{"to":"%s","data": "%s"}]}`, toStr, codeStr) if !self.ConfirmTransaction(jsontx) { err := fmt.Errorf("Transaction not confirmed") return "", err } if len(toStr) > 0 && toStr != "0x" && !isAddress(toStr) { return "", errors.New("Invalid address") } var ( from = common.HexToAddress(fromStr) to = common.HexToAddress(toStr) value = common.Big(valueStr) gas *big.Int price *big.Int data []byte contractCreation bool ) if len(gasStr) == 0 { gas = DefaultGas() } else { gas = common.Big(gasStr) } if len(gasPriceStr) == 0 { price = self.DefaultGasPrice() } else { price = common.Big(gasPriceStr) } data = common.FromHex(codeStr) if len(toStr) == 0 { contractCreation = true } // 2015-05-18 Is this still needed? // TODO if no_private_key then //if _, exists := p.register[args.From]; exists { // p.register[args.From] = append(p.register[args.From], args) //} else { /* account := accounts.Get(common.FromHex(args.From)) if account != nil { if account.Unlocked() { if !unlockAccount(account) { return } } result, _ := account.Transact(common.FromHex(args.To), common.FromHex(args.Value), common.FromHex(args.Gas), common.FromHex(args.GasPrice), common.FromHex(args.Data)) if len(result) > 0 { *reply = common.ToHex(result) } } else if _, exists := p.register[args.From]; exists { p.register[ags.From] = append(p.register[args.From], args) } */ self.transactMu.Lock() defer self.transactMu.Unlock() var nonce uint64 if len(nonceStr) != 0 { nonce = common.Big(nonceStr).Uint64() } else { state := self.backend.TxPool().State() nonce = state.GetNonce(from) } var tx *types.Transaction if contractCreation { tx = types.NewContractCreation(nonce, value, gas, price, data) } else { tx = types.NewTransaction(nonce, to, value, gas, price, data) } signed, err := self.sign(tx, from, false) if err != nil { return "", err } if err = self.backend.TxPool().Add(signed); err != nil { return "", err } if contractCreation { addr := crypto.CreateAddress(from, nonce) glog.V(logger.Info).Infof("Tx(%s) created: %s\n", signed.Hash().Hex(), addr.Hex()) } else { glog.V(logger.Info).Infof("Tx(%s) to: %s\n", signed.Hash().Hex(), tx.To().Hex()) } return signed.Hash().Hex(), nil }