Changed the way transactions are being added to the transaction pool

This commit is contained in:
obscuren 2014-12-01 20:18:09 +01:00
parent a3559c5e1b
commit 6dc46d3341
15 changed files with 239 additions and 98 deletions

@ -314,11 +314,10 @@ out:
// sm.eth.EventMux().Post(NewBlockEvent{block})
// otherwise process and don't emit anything
if len(blocks) > 0 {
chainManager := self.eth.ChainManager()
// Test and import
bchain := chain.NewChain(blocks)
_, err := chainManager.TestChain(bchain)
if err != nil && !chain.IsTDError(err) {
chainman := self.eth.ChainManager()
err := chainman.InsertChain(blocks)
if err != nil {
poollogger.Debugln(err)
self.Reset()
@ -332,12 +331,37 @@ out:
self.peer.StopWithReason(DiscBadPeer)
self.td = ethutil.Big0
self.peer = nil
} else {
chainManager.InsertChain(bchain)
for _, block := range blocks {
self.Remove(block.Hash())
}
}
/*
// Test and import
bchain := chain.NewChain(blocks)
_, err := chainManager.TestChain(bchain)
if err != nil && !chain.IsTDError(err) {
poollogger.Debugln(err)
self.Reset()
if self.peer != nil && self.peer.conn != nil {
poollogger.Debugf("Punishing peer for supplying bad chain (%v)\n", self.peer.conn.RemoteAddr())
}
// This peer gave us bad hashes and made us fetch a bad chain, therefor he shall be punished.
self.eth.BlacklistPeer(self.peer)
self.peer.StopWithReason(DiscBadPeer)
self.td = ethutil.Big0
self.peer = nil
} else {
chainManager.InsertChain(bchain)
for _, block := range blocks {
self.Remove(block.Hash())
}
}
*/
}
}
}

@ -246,7 +246,7 @@ func (sm *BlockManager) ProcessWithParent(block, parent *Block) (td *big.Int, me
return
}
state.Update(nil)
state.Update(ethutil.Big0)
if !block.State().Cmp(state) {
err = fmt.Errorf("invalid merkle root. received=%x got=%x", block.Root(), state.Root())

@ -321,6 +321,24 @@ func NewChain(blocks Blocks) *BlockChain {
return chain
}
// This function assumes you've done your checking. No checking is done at this stage anymore
func (self *ChainManager) InsertChain(chain Blocks) error {
for _, block := range chain {
td, messages, err := self.Ethereum.BlockManager().Process(block)
if err != nil {
return err
}
self.add(block)
self.SetTotalDifficulty(td)
self.Ethereum.EventMux().Post(NewBlockEvent{block})
self.Ethereum.EventMux().Post(messages)
}
return nil
}
/*
// This function assumes you've done your checking. No checking is done at this stage anymore
func (self *ChainManager) InsertChain(chain *BlockChain) {
for e := chain.Front(); e != nil; e = e.Next() {
@ -338,7 +356,9 @@ func (self *ChainManager) InsertChain(chain *BlockChain) {
chainlogger.Infof("Imported %d blocks. #%v (%x) / %#v (%x)", chain.Len(), front.Number, front.Hash()[0:4], back.Number, back.Hash()[0:4])
}
}
*/
/*
func (self *ChainManager) TestChain(chain *BlockChain) (td *big.Int, err error) {
self.workingChain = chain
defer func() { self.workingChain = nil }()
@ -381,3 +401,4 @@ func (self *ChainManager) TestChain(chain *BlockChain) (td *big.Int, err error)
return
}
*/

@ -79,12 +79,7 @@ func (tx *Transaction) IsContract() bool {
func (tx *Transaction) CreationAddress(state *state.State) []byte {
// Generate a new address
addr := crypto.Sha3(ethutil.NewValue([]interface{}{tx.Sender(), tx.Nonce}).Encode())[12:]
//for i := uint64(0); state.GetStateObject(addr) != nil; i++ {
// addr = crypto.Sha3(ethutil.NewValue([]interface{}{tx.Sender(), tx.Nonce + i}).Encode())[12:]
//}
return addr
return crypto.Sha3(ethutil.NewValue([]interface{}{tx.Sender(), tx.Nonce}).Encode())[12:]
}
func (tx *Transaction) Signature(key []byte) []byte {

@ -114,7 +114,6 @@ func (pool *TxPool) ValidateTransaction(tx *Transaction) error {
}
// Get the sender
//sender := pool.Ethereum.BlockManager().procState.GetAccount(tx.Sender())
sender := pool.Ethereum.BlockManager().CurrentState().GetAccount(tx.Sender())
totAmount := new(big.Int).Set(tx.Value)
@ -136,6 +135,34 @@ func (pool *TxPool) ValidateTransaction(tx *Transaction) error {
return nil
}
func (self *TxPool) Add(tx *Transaction) error {
hash := tx.Hash()
foundTx := FindTx(self.pool, func(tx *Transaction, e *list.Element) bool {
return bytes.Compare(tx.Hash(), hash) == 0
})
if foundTx != nil {
return fmt.Errorf("Known transaction (%x)", hash[0:4])
}
err := self.ValidateTransaction(tx)
if err != nil {
return err
}
self.addTransaction(tx)
tmp := make([]byte, 4)
copy(tmp, tx.Recipient)
txplogger.Debugf("(t) %x => %x (%v) %x\n", tx.Sender()[:4], tmp, tx.Value, tx.Hash())
// Notify the subscribers
self.Ethereum.EventMux().Post(TxPreEvent{tx})
return nil
}
func (pool *TxPool) queueHandler() {
out:
for {
@ -172,9 +199,11 @@ out:
}
}
/*
func (pool *TxPool) QueueTransaction(tx *Transaction) {
pool.queueChan <- tx
}
*/
func (pool *TxPool) CurrentTransactions() []*Transaction {
pool.mutex.Lock()

@ -26,7 +26,6 @@ import (
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/xeth"
)
type plugin struct {
@ -46,12 +45,12 @@ func (gui *Gui) LogPrint(level logger.LogLevel, msg string) {
}
*/
}
func (gui *Gui) Transact(recipient, value, gas, gasPrice, d string) (*xeth.JSReceipt, error) {
func (gui *Gui) Transact(recipient, value, gas, gasPrice, d string) (string, error) {
var data string
if len(recipient) == 0 {
code, err := ethutil.Compile(d, false)
if err != nil {
return nil, err
return "", err
}
data = ethutil.Bytes2Hex(code)
} else {

@ -127,7 +127,11 @@ func (self *UiLib) PastPeers() *ethutil.List {
func (self *UiLib) ImportTx(rlpTx string) {
tx := chain.NewTransactionFromBytes(ethutil.Hex2Bytes(rlpTx))
self.eth.TxPool().QueueTransaction(tx)
//self.eth.TxPool().QueueTransaction(tx)
err := self.eth.TxPool().Add(tx)
if err != nil {
guilogger.Infoln("import tx failed ", err)
}
}
func (self *UiLib) EvalJavascriptFile(path string) {
@ -305,7 +309,7 @@ func mapToTxParams(object map[string]interface{}) map[string]string {
return conv
}
func (self *UiLib) Transact(params map[string]interface{}) (*xeth.JSReceipt, error) {
func (self *UiLib) Transact(params map[string]interface{}) (string, error) {
object := mapToTxParams(params)
return self.JSXEth.Transact(

@ -62,6 +62,16 @@ func S256(x *big.Int) *big.Int {
}
}
func FirstBitSet(v *big.Int) *big.Int {
for i := 0; i < v.BitLen(); i++ {
if v.Bit(i) > 0 {
return big.NewInt(int64(i))
}
}
return big.NewInt(int64(v.BitLen()))
}
// Big to bytes
//
// Returns the bytes of a big integer with the size specified by **base**

@ -203,7 +203,7 @@ func (self *Miner) mine() {
// Accumulate the rewards included for this block
blockManager.AccumelateRewards(block.State(), block, parent)
block.State().Update(nil)
block.State().Update(ethutil.Big0)
minerlogger.Infof("Mining on block. Includes %v transactions", len(transactions))
@ -211,12 +211,13 @@ func (self *Miner) mine() {
nonce := self.pow.Search(block, self.powQuitCh)
if nonce != nil {
block.Nonce = nonce
lchain := chain.NewChain(chain.Blocks{block})
_, err := chainMan.TestChain(lchain)
//lchain := chain.NewChain(chain.Blocks{block})
//_, err := chainMan.TestChain(lchain)
err := chainMan.InsertChain(chain.Blocks{block})
if err != nil {
minerlogger.Infoln(err)
} else {
chainMan.InsertChain(lchain)
//chainMan.InsertChain(lchain)
//self.eth.EventMux().Post(chain.NewBlockEvent{block})
self.eth.Broadcast(wire.MsgBlockTy, []interface{}{block.Value().Val})

@ -430,7 +430,13 @@ func (p *Peer) HandleInbound() {
// processing when a new block is found
for i := 0; i < msg.Data.Len(); i++ {
tx := chain.NewTransactionFromValue(msg.Data.Get(i))
p.ethereum.TxPool().QueueTransaction(tx)
err := p.ethereum.TxPool().Add(tx)
if err != nil {
peerlogger.Infoln(err)
} else {
peerlogger.Infof("tx OK (%x)\n", tx.Hash()[0:4])
}
//p.ethereum.TxPool().QueueTransaction(tx)
}
case wire.MsgGetPeersTy:
// Peer asked for list of connected peers

@ -249,7 +249,6 @@ func (s *State) Reset() {
continue
}
//stateObject.state.Reset()
stateObject.Reset()
}
@ -281,6 +280,7 @@ func (self *State) Update(gasUsed *big.Int) {
var deleted bool
// Refund any gas that's left
// XXX THIS WILL CHANGE IN POC8
uhalf := new(big.Int).Div(gasUsed, ethutil.Big2)
for addr, refs := range self.refund {
for _, ref := range refs {
@ -289,6 +289,7 @@ func (self *State) Update(gasUsed *big.Int) {
self.GetStateObject([]byte(addr)).AddBalance(refund.Mul(refund, ref.price))
}
}
self.refund = make(map[string][]refund)
for _, stateObject := range self.stateObjects {
if stateObject.remove {

@ -214,7 +214,7 @@ func (c *StateObject) ConvertGas(gas, price *big.Int) error {
func (self *StateObject) SetGasPool(gasLimit *big.Int) {
self.gasPool = new(big.Int).Set(gasLimit)
statelogger.DebugDetailf("%x: fuel (+ %v)", self.Address(), self.gasPool)
statelogger.Debugf("%x: gas (+ %v)", self.Address(), self.gasPool)
}
func (self *StateObject) BuyGas(gas, price *big.Int) error {

@ -151,7 +151,7 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
// Stack checks only
case ISZERO, CALLDATALOAD, POP, JUMP, NOT: // 1
require(1)
case ADD, SUB, DIV, SDIV, MOD, SMOD, EXP, LT, GT, SLT, SGT, EQ, AND, OR, XOR, BYTE: // 2
case ADD, SUB, DIV, SDIV, MOD, SMOD, LT, GT, SLT, SGT, EQ, AND, OR, XOR, BYTE: // 2
require(2)
case ADDMOD, MULMOD: // 3
require(3)
@ -169,6 +169,15 @@ func (self *DebugVm) RunClosure(closure *Closure) (ret []byte, err error) {
gas.Set(GasLog)
addStepGasUsage(new(big.Int).Mul(big.NewInt(int64(n)), GasLog))
addStepGasUsage(new(big.Int).Add(mSize, mStart))
case EXP:
require(2)
expGas := ethutil.FirstBitSet(stack.data[stack.Len()-2])
expGas.Div(expGas, u256(8))
expGas.Sub(u256(32), expGas)
expGas.Add(expGas, u256(1))
gas.Set(expGas)
// Gas only
case STOP:
gas.Set(ethutil.Big0)

@ -177,19 +177,25 @@ func (self *JSXEth) FromNumber(str string) string {
return ethutil.BigD(ethutil.Hex2Bytes(str)).String()
}
func (self *JSXEth) Transact(key, toStr, valueStr, gasStr, gasPriceStr, codeStr string) (*JSReceipt, error) {
var hash []byte
var contractCreation bool
if len(toStr) == 0 {
contractCreation = true
func (self *JSXEth) Transact(key, toStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
var (
to []byte
value = ethutil.NewValue(valueStr)
gas = ethutil.NewValue(gasStr)
gasPrice = ethutil.NewValue(gasPriceStr)
data []byte
)
if ethutil.IsHex(codeStr) {
data = ethutil.Hex2Bytes(codeStr[2:])
} else {
// Check if an address is stored by this address
addr := self.World().Config().Get("NameReg").StorageString(toStr).Bytes()
if len(addr) > 0 {
hash = addr
} else {
hash = ethutil.Hex2Bytes(toStr)
}
data = ethutil.Hex2Bytes(codeStr)
}
if ethutil.IsHex(toStr) {
to = ethutil.Hex2Bytes(toStr[2:])
} else {
to = ethutil.Hex2Bytes(toStr)
}
var keyPair *crypto.KeyPair
@ -201,47 +207,77 @@ func (self *JSXEth) Transact(key, toStr, valueStr, gasStr, gasPriceStr, codeStr
}
if err != nil {
return nil, err
return "", err
}
var (
value = ethutil.Big(valueStr)
gas = ethutil.Big(gasStr)
gasPrice = ethutil.Big(gasPriceStr)
data []byte
tx *chain.Transaction
)
if ethutil.IsHex(codeStr) {
data = ethutil.Hex2Bytes(codeStr[2:])
} else {
data = ethutil.Hex2Bytes(codeStr)
tx, err := self.XEth.Transact(keyPair, to, value, gas, gasPrice, data)
if err != nil {
return "", err
}
if chain.IsContractAddr(to) {
return ethutil.Bytes2Hex(tx.CreationAddress(nil)), nil
}
if contractCreation {
tx = chain.NewContractCreationTx(value, gas, gasPrice, data)
} else {
tx = chain.NewTransactionMessage(hash, value, gas, gasPrice, data)
}
return ethutil.Bytes2Hex(tx.Hash()), nil
acc := self.obj.BlockManager().TransState().GetOrNewStateObject(keyPair.Address())
tx.Nonce = acc.Nonce
acc.Nonce += 1
self.obj.BlockManager().TransState().UpdateStateObject(acc)
/*
var hash []byte
var contractCreation bool
if len(toStr) == 0 {
contractCreation = true
} else {
// Check if an address is stored by this address
addr := self.World().Config().Get("NameReg").StorageString(toStr).Bytes()
if len(addr) > 0 {
hash = addr
} else {
hash = ethutil.Hex2Bytes(toStr)
}
}
tx.Sign(keyPair.PrivateKey)
self.obj.TxPool().QueueTransaction(tx)
if contractCreation {
pipelogger.Infof("Contract addr %x", tx.CreationAddress(self.World().State()))
}
var (
value = ethutil.Big(valueStr)
gas = ethutil.Big(gasStr)
gasPrice = ethutil.Big(gasPriceStr)
data []byte
tx *chain.Transaction
)
return NewJSReciept(contractCreation, tx.CreationAddress(self.World().State()), tx.Hash(), keyPair.Address()), nil
if ethutil.IsHex(codeStr) {
data = ethutil.Hex2Bytes(codeStr[2:])
} else {
data = ethutil.Hex2Bytes(codeStr)
}
if contractCreation {
tx = chain.NewContractCreationTx(value, gas, gasPrice, data)
} else {
tx = chain.NewTransactionMessage(hash, value, gas, gasPrice, data)
}
acc := self.obj.BlockManager().TransState().GetOrNewStateObject(keyPair.Address())
tx.Nonce = acc.Nonce
acc.Nonce += 1
self.obj.BlockManager().TransState().UpdateStateObject(acc)
tx.Sign(keyPair.PrivateKey)
self.obj.TxPool().QueueTransaction(tx)
if contractCreation {
pipelogger.Infof("Contract addr %x", tx.CreationAddress(self.World().State()))
}
return NewJSReciept(contractCreation, tx.CreationAddress(self.World().State()), tx.Hash(), keyPair.Address()), nil
*/
}
func (self *JSXEth) PushTx(txStr string) (*JSReceipt, error) {
tx := chain.NewTransactionFromBytes(ethutil.Hex2Bytes(txStr))
self.obj.TxPool().QueueTransaction(tx)
err := self.obj.TxPool().Add(tx)
if err != nil {
return nil, err
}
return NewJSReciept(tx.CreatesContract(), tx.CreationAddress(self.World().State()), tx.Hash(), tx.Sender()), nil
}

@ -6,7 +6,6 @@ package xeth
import (
"fmt"
"strings"
"github.com/ethereum/go-ethereum/chain"
"github.com/ethereum/go-ethereum/crypto"
@ -93,7 +92,7 @@ func (self *XEth) Exists(addr []byte) bool {
return self.World().Get(addr) != nil
}
func (self *XEth) TransactString(key *crypto.KeyPair, rec string, value, gas, price *ethutil.Value, data []byte) ([]byte, error) {
func (self *XEth) TransactString(key *crypto.KeyPair, rec string, value, gas, price *ethutil.Value, data []byte) (*chain.Transaction, error) {
// Check if an address is stored by this address
var hash []byte
addr := self.World().Config().Get("NameReg").StorageString(rec).Bytes()
@ -108,55 +107,62 @@ func (self *XEth) TransactString(key *crypto.KeyPair, rec string, value, gas, pr
return self.Transact(key, hash, value, gas, price, data)
}
func (self *XEth) Transact(key *crypto.KeyPair, rec []byte, value, gas, price *ethutil.Value, data []byte) ([]byte, error) {
func (self *XEth) Transact(key *crypto.KeyPair, to []byte, value, gas, price *ethutil.Value, data []byte) (*chain.Transaction, error) {
var hash []byte
var contractCreation bool
if rec == nil {
if chain.IsContractAddr(to) {
contractCreation = true
} else {
// Check if an address is stored by this address
addr := self.World().Config().Get("NameReg").Storage(to).Bytes()
if len(addr) > 0 {
hash = addr
} else {
hash = to
}
}
var tx *chain.Transaction
// Compile and assemble the given data
if contractCreation {
script, err := ethutil.Compile(string(data), false)
if err != nil {
return nil, err
}
tx = chain.NewContractCreationTx(value.BigInt(), gas.BigInt(), price.BigInt(), script)
tx = chain.NewContractCreationTx(value.BigInt(), gas.BigInt(), price.BigInt(), data)
} else {
data := ethutil.StringToByteFunc(string(data), func(s string) (ret []byte) {
slice := strings.Split(s, "\n")
for _, dataItem := range slice {
d := ethutil.FormatData(dataItem)
ret = append(ret, d...)
}
return
})
tx = chain.NewTransactionMessage(hash, value.BigInt(), gas.BigInt(), price.BigInt(), data)
}
acc := self.blockManager.TransState().GetOrNewStateObject(key.Address())
tx.Nonce = acc.Nonce
acc.Nonce += 1
self.blockManager.TransState().UpdateStateObject(acc)
state := self.blockManager.TransState()
nonce := state.GetNonce(key.Address())
tx.Nonce = nonce
tx.Sign(key.PrivateKey)
self.obj.TxPool().QueueTransaction(tx)
err := self.obj.TxPool().Add(tx)
if err != nil {
return nil, err
}
state.SetNonce(key.Address(), nonce+1)
if contractCreation {
addr := tx.CreationAddress(self.World().State())
pipelogger.Infof("Contract addr %x\n", addr)
return addr, nil
}
return tx.Hash(), nil
return tx, nil
//acc := self.blockManager.TransState().GetOrNewStateObject(key.Address())
//self.obj.TxPool().QueueTransaction(tx)
//acc.Nonce += 1
//self.blockManager.TransState().UpdateStateObject(acc)
}
func (self *XEth) PushTx(tx *chain.Transaction) ([]byte, error) {
self.obj.TxPool().QueueTransaction(tx)
err := self.obj.TxPool().Add(tx)
if err != nil {
return nil, err
}
//self.obj.TxPool().QueueTransaction(tx)
if tx.Recipient == nil {
addr := tx.CreationAddress(self.World().State())
pipelogger.Infof("Contract addr %x\n", addr)