aboutsummaryrefslogtreecommitdiffstats
path: root/xeth/xeth.go
diff options
context:
space:
mode:
Diffstat (limited to 'xeth/xeth.go')
-rw-r--r--xeth/xeth.go101
1 files changed, 97 insertions, 4 deletions
diff --git a/xeth/xeth.go b/xeth/xeth.go
index ac59069d5..beda8871c 100644
--- a/xeth/xeth.go
+++ b/xeth/xeth.go
@@ -11,6 +11,7 @@ import (
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/compiler"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
@@ -51,6 +52,9 @@ type XEth struct {
// regmut sync.Mutex
// register map[string][]*interface{} // TODO improve return type
+ solcPath string
+ solc *compiler.Solidity
+
agent *miner.RemoteAgent
}
@@ -69,7 +73,6 @@ func New(eth *eth.Ethereum, frontend Frontend) *XEth {
agent: miner.NewRemoteAgent(),
}
eth.Miner().Register(xeth.agent)
-
if frontend == nil {
xeth.frontend = dummyFrontend{}
}
@@ -151,9 +154,38 @@ func (self *XEth) AtStateNum(num int64) *XEth {
return self.WithState(st)
}
+// applies queued transactions originating from address onto the latest state
+// and creates a block
+// only used in tests
+// - could be removed in favour of mining on testdag (natspec e2e + networking)
+// + filters
+func (self *XEth) ApplyTestTxs(statedb *state.StateDB, address common.Address, txc uint64) (uint64, *XEth) {
+
+ block := self.backend.ChainManager().NewBlock(address)
+ coinbase := statedb.GetStateObject(address)
+ coinbase.SetGasPool(big.NewInt(10000000))
+ txs := self.backend.TxPool().GetQueuedTransactions()
+
+ for i := 0; i < len(txs); i++ {
+ for _, tx := range txs {
+ if tx.Nonce() == txc {
+ _, _, err := core.ApplyMessage(core.NewEnv(statedb, self.backend.ChainManager(), tx, block), tx, coinbase)
+ if err != nil {
+ panic(err)
+ }
+ txc++
+ }
+ }
+ }
+
+ xeth := self.WithState(statedb)
+ return txc, xeth
+}
+
func (self *XEth) WithState(statedb *state.StateDB) *XEth {
xeth := &XEth{
- backend: self.backend,
+ backend: self.backend,
+ frontend: self.frontend,
}
xeth.state = NewState(xeth, statedb)
@@ -162,6 +194,44 @@ func (self *XEth) WithState(statedb *state.StateDB) *XEth {
func (self *XEth) State() *State { return self.state }
+// subscribes to new head block events and
+// waits until blockchain height is greater n at any time
+// given the current head, waits for the next chain event
+// sets the state to the current head
+// loop is async and quit by closing the channel
+// used in tests and JS console debug module to control advancing private chain manually
+// Note: this is not threadsafe, only called in JS single process and tests
+func (self *XEth) UpdateState() (wait chan *big.Int) {
+ wait = make(chan *big.Int)
+ go func() {
+ sub := self.backend.EventMux().Subscribe(core.ChainHeadEvent{})
+ var m, n *big.Int
+ var ok bool
+ out:
+ for {
+ select {
+ case event := <-sub.Chan():
+ ev, ok := event.(core.ChainHeadEvent)
+ if ok {
+ m = ev.Block.Number()
+ if n != nil && n.Cmp(m) < 0 {
+ wait <- n
+ n = nil
+ }
+ statedb := state.New(ev.Block.Root(), self.backend.StateDb())
+ self.state = NewState(self, statedb)
+ }
+ case n, ok = <-wait:
+ if !ok {
+ break out
+ }
+ }
+ }
+ sub.Unsubscribe()
+ }()
+ return
+}
+
func (self *XEth) Whisper() *Whisper { return self.whisper }
func (self *XEth) getBlockByHeight(height int64) *types.Block {
@@ -262,6 +332,23 @@ func (self *XEth) Accounts() []string {
return accountAddresses
}
+// accessor for solidity compiler.
+// memoized if available, retried on-demand if not
+func (self *XEth) Solc() (*compiler.Solidity, error) {
+ var err error
+ if self.solc == nil {
+ self.solc, err = compiler.New(self.solcPath)
+ }
+ return self.solc, err
+}
+
+// set in js console via admin interface or wrapper from cli flags
+func (self *XEth) SetSolc(solcPath string) (*compiler.Solidity, error) {
+ self.solcPath = solcPath
+ self.solc = nil
+ return self.Solc()
+}
+
func (self *XEth) DbPut(key, val []byte) bool {
self.backend.ExtraDb().Put(key, val)
return true
@@ -643,12 +730,18 @@ func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr st
}
func (self *XEth) ConfirmTransaction(tx string) bool {
-
return self.frontend.ConfirmTransaction(tx)
-
}
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
+ }
+
var (
from = common.HexToAddress(fromStr)
to = common.HexToAddress(toStr)