diff options
-rw-r--r-- | cmd/evm/main.go | 112 | ||||
-rw-r--r-- | cmd/geth/main.go | 6 | ||||
-rw-r--r-- | cmd/utils/flags.go | 18 | ||||
-rw-r--r-- | core/bench_test.go | 2 | ||||
-rw-r--r-- | core/chain_makers_test.go | 5 | ||||
-rw-r--r-- | core/chain_manager.go | 30 | ||||
-rw-r--r-- | core/chain_manager_test.go | 1 | ||||
-rw-r--r-- | core/chain_util.go | 13 | ||||
-rw-r--r-- | core/fees.go | 2 | ||||
-rw-r--r-- | core/genesis.go | 13 | ||||
-rw-r--r-- | core/transaction_util.go | 42 | ||||
-rw-r--r-- | core/types/block.go | 4 | ||||
-rw-r--r-- | crypto/curve.go | 9 | ||||
-rw-r--r-- | eth/backend.go | 11 | ||||
-rw-r--r-- | eth/handler.go | 1 | ||||
-rw-r--r-- | eth/protocol.go | 2 | ||||
-rw-r--r-- | eth/protocol_test.go | 4 | ||||
-rw-r--r-- | ethdb/database.go | 41 | ||||
-rw-r--r-- | ethdb/database_test.go | 3 | ||||
-rw-r--r-- | jsre/ethereum_js.go | 422 | ||||
-rwxr-xr-x | params/protocol_params.go | 92 | ||||
-rw-r--r-- | rpc/api/miner.go | 8 | ||||
-rw-r--r-- | tests/block_test.go | 8 | ||||
-rw-r--r-- | trie/cache.go | 4 | ||||
-rw-r--r-- | xeth/xeth.go | 2 |
25 files changed, 629 insertions, 226 deletions
diff --git a/cmd/evm/main.go b/cmd/evm/main.go index ab4d3f82a..965994382 100644 --- a/cmd/evm/main.go +++ b/cmd/evm/main.go @@ -18,79 +18,129 @@ package main import ( - "flag" "fmt" - "log" "math/big" "os" "runtime" "time" + "github.com/codegangsta/cli" + "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/logger" ) var ( - code = flag.String("code", "", "evm code") - loglevel = flag.Int("log", 4, "log level") - gas = flag.String("gas", "1000000000", "gas amount") - price = flag.String("price", "0", "gas price") - value = flag.String("value", "0", "tx value") - dump = flag.Bool("dump", false, "dump state after run") - data = flag.String("data", "", "data") + app *cli.App + DebugFlag = cli.BoolFlag{ + Name: "debug", + Usage: "output full trace logs", + } + CodeFlag = cli.StringFlag{ + Name: "code", + Usage: "EVM code", + } + GasFlag = cli.StringFlag{ + Name: "gas", + Usage: "gas limit for the evm", + Value: "10000000000", + } + PriceFlag = cli.StringFlag{ + Name: "price", + Usage: "price set for the evm", + Value: "0", + } + ValueFlag = cli.StringFlag{ + Name: "value", + Usage: "value set for the evm", + Value: "0", + } + DumpFlag = cli.BoolFlag{ + Name: "dump", + Usage: "dumps the state after the run", + } + InputFlag = cli.StringFlag{ + Name: "input", + Usage: "input for the EVM", + } + SysStatFlag = cli.BoolFlag{ + Name: "sysstat", + Usage: "display system stats", + } ) -func perr(v ...interface{}) { - fmt.Println(v...) - //os.Exit(1) +func init() { + app = utils.NewApp("0.2", "the evm command line interface") + app.Flags = []cli.Flag{ + DebugFlag, + SysStatFlag, + CodeFlag, + GasFlag, + PriceFlag, + ValueFlag, + DumpFlag, + InputFlag, + } + app.Action = run } -func main() { - flag.Parse() - - logger.AddLogSystem(logger.NewStdLogSystem(os.Stdout, log.LstdFlags, logger.LogLevel(*loglevel))) +func run(ctx *cli.Context) { + vm.Debug = ctx.GlobalBool(DebugFlag.Name) - vm.Debug = true db, _ := ethdb.NewMemDatabase() statedb := state.New(common.Hash{}, db) sender := statedb.CreateAccount(common.StringToAddress("sender")) receiver := statedb.CreateAccount(common.StringToAddress("receiver")) - receiver.SetCode(common.Hex2Bytes(*code)) + receiver.SetCode(common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name))) - vmenv := NewEnv(statedb, common.StringToAddress("evmuser"), common.Big(*value)) + vmenv := NewEnv(statedb, common.StringToAddress("evmuser"), common.Big(ctx.GlobalString(ValueFlag.Name))) tstart := time.Now() + ret, e := vmenv.Call( + sender, + receiver.Address(), + common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), + common.Big(ctx.GlobalString(GasFlag.Name)), + common.Big(ctx.GlobalString(PriceFlag.Name)), + common.Big(ctx.GlobalString(ValueFlag.Name)), + ) + vmdone := time.Since(tstart) - ret, e := vmenv.Call(sender, receiver.Address(), common.Hex2Bytes(*data), common.Big(*gas), common.Big(*price), common.Big(*value)) - - logger.Flush() if e != nil { - perr(e) + fmt.Println(e) + os.Exit(1) } - if *dump { + if ctx.GlobalBool(DumpFlag.Name) { fmt.Println(string(statedb.Dump())) } - vm.StdErrFormat(vmenv.StructLogs()) - var mem runtime.MemStats - runtime.ReadMemStats(&mem) - fmt.Printf("vm took %v\n", time.Since(tstart)) - fmt.Printf(`alloc: %d + if ctx.GlobalBool(SysStatFlag.Name) { + var mem runtime.MemStats + runtime.ReadMemStats(&mem) + fmt.Printf("vm took %v\n", vmdone) + fmt.Printf(`alloc: %d tot alloc: %d no. malloc: %d heap alloc: %d heap objs: %d num gc: %d `, mem.Alloc, mem.TotalAlloc, mem.Mallocs, mem.HeapAlloc, mem.HeapObjects, mem.NumGC) + } - fmt.Printf("%x\n", ret) + fmt.Printf("OUT: 0x%x\n", ret) +} + +func main() { + if err := app.Run(os.Args); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } } type VMEnv struct { diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 6f92eb6b1..68a2c79e2 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -49,7 +49,7 @@ import ( const ( ClientIdentifier = "Geth" - Version = "0.9.39" + Version = "1.0.0" ) var ( @@ -276,11 +276,11 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso utils.IdentityFlag, utils.UnlockedAccountFlag, utils.PasswordFileFlag, - utils.GenesisNonceFlag, utils.GenesisFileFlag, utils.BootnodesFlag, utils.DataDirFlag, utils.BlockchainVersionFlag, + utils.CacheFlag, utils.JSpathFlag, utils.ListenPortFlag, utils.MaxPeersFlag, @@ -501,7 +501,7 @@ func blockRecovery(ctx *cli.Context) { cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx) utils.CheckLegalese(cfg.DataDir) - blockDb, err := ethdb.NewLDBDatabase(filepath.Join(cfg.DataDir, "blockchain")) + blockDb, err := ethdb.NewLDBDatabase(filepath.Join(cfg.DataDir, "blockchain"), cfg.DatabaseCache) if err != nil { glog.Fatalln("could not open db:", err) } diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 95217300b..b66fe24cc 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -126,6 +126,11 @@ var ( Name: "natspec", Usage: "Enable NatSpec confirmation notice", } + CacheFlag = cli.IntFlag{ + Name: "cache", + Usage: "Megabytes of memory allocated to internal caching", + Value: 0, + } // miner settings MinerThreadsFlag = cli.IntFlag{ @@ -149,7 +154,7 @@ var ( GasPriceFlag = cli.StringFlag{ Name: "gasprice", Usage: "Sets the minimal gasprice when mining transactions", - Value: new(big.Int).Mul(big.NewInt(1), common.Szabo).String(), + Value: new(big.Int).Mul(big.NewInt(500), common.Shannon).String(), } UnlockedAccountFlag = cli.StringFlag{ @@ -384,6 +389,7 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config { GenesisNonce: ctx.GlobalInt(GenesisNonceFlag.Name), GenesisFile: ctx.GlobalString(GenesisFileFlag.Name), BlockChainVersion: ctx.GlobalInt(BlockchainVersionFlag.Name), + DatabaseCache: ctx.GlobalInt(CacheFlag.Name), SkipBcVersionCheck: false, NetworkId: ctx.GlobalInt(NetworkIdFlag.Name), LogFile: ctx.GlobalString(LogFileFlag.Name), @@ -425,15 +431,17 @@ func SetupLogger(ctx *cli.Context) { // MakeChain creates a chain manager from set command line flags. func MakeChain(ctx *cli.Context) (chain *core.ChainManager, blockDB, stateDB, extraDB common.Database) { - dd := ctx.GlobalString(DataDirFlag.Name) + datadir := ctx.GlobalString(DataDirFlag.Name) + cache := ctx.GlobalInt(CacheFlag.Name) + var err error - if blockDB, err = ethdb.NewLDBDatabase(filepath.Join(dd, "blockchain")); err != nil { + if blockDB, err = ethdb.NewLDBDatabase(filepath.Join(datadir, "blockchain"), cache); err != nil { Fatalf("Could not open database: %v", err) } - if stateDB, err = ethdb.NewLDBDatabase(filepath.Join(dd, "state")); err != nil { + if stateDB, err = ethdb.NewLDBDatabase(filepath.Join(datadir, "state"), cache); err != nil { Fatalf("Could not open database: %v", err) } - if extraDB, err = ethdb.NewLDBDatabase(filepath.Join(dd, "extra")); err != nil { + if extraDB, err = ethdb.NewLDBDatabase(filepath.Join(datadir, "extra"), cache); err != nil { Fatalf("Could not open database: %v", err) } diff --git a/core/bench_test.go b/core/bench_test.go index c5c5b5b72..67ba15970 100644 --- a/core/bench_test.go +++ b/core/bench_test.go @@ -153,7 +153,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) { b.Fatalf("cannot create temporary directory: %v", err) } defer os.RemoveAll(dir) - db, err = ethdb.NewLDBDatabase(dir) + db, err = ethdb.NewLDBDatabase(dir, 0) if err != nil { b.Fatalf("cannot create temporary database: %v", err) } diff --git a/core/chain_makers_test.go b/core/chain_makers_test.go index 750ec3809..98a585f9b 100644 --- a/core/chain_makers_test.go +++ b/core/chain_makers_test.go @@ -28,6 +28,9 @@ import ( ) func ExampleGenerateChain() { + params.MinGasLimit = big.NewInt(125000) // Minimum the gas limit may ever be. + params.GenesisGasLimit = big.NewInt(3141592) // Gas limit of the Genesis block. + var ( key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") @@ -90,5 +93,5 @@ func ExampleGenerateChain() { // last block: #5 // balance of addr1: 989000 // balance of addr2: 10000 - // balance of addr3: 5906250000000001000 + // balance of addr3: 19687500000000001000 } diff --git a/core/chain_manager.go b/core/chain_manager.go index 4ad48c24c..c2e89a10d 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -73,9 +73,6 @@ type ChainManager struct { lastBlockHash common.Hash currentGasLimit *big.Int - transState *state.StateDB - txState *state.ManagedState - cache *lru.Cache // cache is the LRU caching futureBlocks *lru.Cache // future blocks are blocks added for later processing @@ -101,13 +98,7 @@ func NewChainManager(blockDb, stateDb, extraDb common.Database, pow pow.PoW, mux bc.genesisBlock = bc.GetBlockByNumber(0) if bc.genesisBlock == nil { - // XXX Uncomment me before Frontier - //return nil, ErrNoGenesis - genesis, err := WriteTestNetGenesisBlock(bc.stateDb, bc.blockDb, 42) - if err != nil { - glog.Fatalln("genisis err", err) - } - bc.genesisBlock = genesis + return nil, ErrNoGenesis } if err := bc.setLastState(); err != nil { @@ -128,9 +119,7 @@ func NewChainManager(blockDb, stateDb, extraDb common.Database, pow pow.PoW, mux } } - bc.transState = bc.State().Copy() // Take ownership of this particular state - bc.txState = state.ManageState(bc.State().Copy()) bc.futureBlocks, _ = lru.New(maxFutureBlocks) bc.makeCache() @@ -152,9 +141,6 @@ func (bc *ChainManager) SetHead(head *types.Block) { bc.currentBlock = head bc.makeCache() - statedb := state.New(head.Root(), bc.stateDb) - bc.txState = state.ManageState(statedb) - bc.transState = statedb.Copy() bc.setTotalDifficulty(head.Td) bc.insert(head) bc.setLastState() @@ -203,17 +189,6 @@ func (self *ChainManager) State() *state.StateDB { return state.New(self.CurrentBlock().Root(), self.stateDb) } -func (self *ChainManager) TransState() *state.StateDB { - self.tsmu.RLock() - defer self.tsmu.RUnlock() - - return self.transState -} - -func (self *ChainManager) setTransState(statedb *state.StateDB) { - self.transState = statedb -} - func (bc *ChainManager) recover() bool { data, _ := bc.blockDb.Get([]byte("checkpoint")) if len(data) != 0 { @@ -529,9 +504,6 @@ func (self *ChainManager) WriteBlock(block *types.Block, queued bool) (status wr self.insert(block) self.mu.Unlock() - self.setTransState(state.New(block.Root(), self.stateDb)) - self.txState.SetState(state.New(block.Root(), self.stateDb)) - status = CanonStatTy } else { status = SideStatTy diff --git a/core/chain_manager_test.go b/core/chain_manager_test.go index 2602afe19..f0c097df6 100644 --- a/core/chain_manager_test.go +++ b/core/chain_manager_test.go @@ -392,7 +392,6 @@ func chm(genesis *types.Block, db common.Database) *ChainManager { bc.futureBlocks, _ = lru.New(100) bc.processor = bproc{} bc.ResetWithGenesisBlock(genesis) - bc.txState = state.ManageState(bc.State()) return bc } diff --git a/core/chain_util.go b/core/chain_util.go index 4e6665568..326bf13fb 100644 --- a/core/chain_util.go +++ b/core/chain_util.go @@ -111,13 +111,22 @@ func GetBlockByNumber(db common.Database, number uint64) *types.Block { return GetBlockByHash(db, common.BytesToHash(key)) } -// WriteHead force writes the current head -func WriteHead(db common.Database, block *types.Block) error { +// WriteCanonNumber writes the canonical hash for the given block +func WriteCanonNumber(db common.Database, block *types.Block) error { key := append(blockNumPre, block.Number().Bytes()...) err := db.Put(key, block.Hash().Bytes()) if err != nil { return err } + return nil +} + +// WriteHead force writes the current head +func WriteHead(db common.Database, block *types.Block) error { + err := WriteCanonNumber(db, block) + if err != nil { + return err + } err = db.Put([]byte("LastBlock"), block.Hash().Bytes()) if err != nil { return err diff --git a/core/fees.go b/core/fees.go index 322bc96f6..0bb26f055 100644 --- a/core/fees.go +++ b/core/fees.go @@ -20,4 +20,4 @@ import ( "math/big" ) -var BlockReward *big.Int = big.NewInt(1.5e+18) +var BlockReward *big.Int = big.NewInt(5e+18) diff --git a/core/genesis.go b/core/genesis.go index 67c3a3b58..4c0323c17 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -27,6 +27,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/params" ) @@ -73,7 +75,7 @@ func WriteGenesisBlock(stateDb, blockDb common.Database, reader io.Reader) (*typ Nonce: types.EncodeNonce(common.String2Big(genesis.Nonce).Uint64()), Time: common.String2Big(genesis.Timestamp).Uint64(), ParentHash: common.HexToHash(genesis.ParentHash), - Extra: common.Hex2Bytes(genesis.ExtraData), + Extra: common.FromHex(genesis.ExtraData), GasLimit: common.String2Big(genesis.GasLimit), Difficulty: difficulty, MixDigest: common.HexToHash(genesis.Mixhash), @@ -82,6 +84,15 @@ func WriteGenesisBlock(stateDb, blockDb common.Database, reader io.Reader) (*typ }, nil, nil, nil) block.Td = difficulty + if block := GetBlockByHash(blockDb, block.Hash()); block != nil { + glog.V(logger.Info).Infoln("Genesis block already in chain. Writing canonical number") + err := WriteCanonNumber(blockDb, block) + if err != nil { + return nil, err + } + return block, nil + } + statedb.Sync() err = WriteBlock(blockDb, block) diff --git a/core/transaction_util.go b/core/transaction_util.go index 54a909ba2..ce2ceac46 100644 --- a/core/transaction_util.go +++ b/core/transaction_util.go @@ -19,9 +19,11 @@ package core import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/rlp" + "github.com/syndtr/goleveldb/leveldb" ) var ( @@ -31,13 +33,21 @@ var ( // PutTransactions stores the transactions in the given database func PutTransactions(db common.Database, block *types.Block, txs types.Transactions) { + batch := new(leveldb.Batch) + _, batchWrite := db.(*ethdb.LDBDatabase) + for i, tx := range block.Transactions() { rlpEnc, err := rlp.EncodeToBytes(tx) if err != nil { glog.V(logger.Debug).Infoln("Failed encoding tx", err) return } - db.Put(tx.Hash().Bytes(), rlpEnc) + + if batchWrite { + batch.Put(tx.Hash().Bytes(), rlpEnc) + } else { + db.Put(tx.Hash().Bytes(), rlpEnc) + } var txExtra struct { BlockHash common.Hash @@ -52,20 +62,44 @@ func PutTransactions(db common.Database, block *types.Block, txs types.Transacti glog.V(logger.Debug).Infoln("Failed encoding tx meta data", err) return } - db.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta) + + if batchWrite { + batch.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta) + } else { + db.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta) + } + } + + if db, ok := db.(*ethdb.LDBDatabase); ok { + if err := db.LDB().Write(batch, nil); err != nil { + glog.V(logger.Error).Infoln("db write err:", err) + } } } // PutReceipts stores the receipts in the current database func PutReceipts(db common.Database, receipts types.Receipts) error { + batch := new(leveldb.Batch) + _, batchWrite := db.(*ethdb.LDBDatabase) + for _, receipt := range receipts { storageReceipt := (*types.ReceiptForStorage)(receipt) bytes, err := rlp.EncodeToBytes(storageReceipt) if err != nil { return err } - err = db.Put(append(receiptsPre, receipt.TxHash[:]...), bytes) - if err != nil { + + if batchWrite { + batch.Put(append(receiptsPre, receipt.TxHash[:]...), bytes) + } else { + err = db.Put(append(receiptsPre, receipt.TxHash[:]...), bytes) + if err != nil { + return err + } + } + } + if db, ok := db.(*ethdb.LDBDatabase); ok { + if err := db.LDB().Write(batch, nil); err != nil { return err } } diff --git a/core/types/block.go b/core/types/block.go index 5a0b2abce..427a3e6cb 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -257,7 +257,7 @@ func (b *Block) DecodeRLP(s *rlp.Stream) error { return nil } -func (b Block) EncodeRLP(w io.Writer) error { +func (b *Block) EncodeRLP(w io.Writer) error { return rlp.Encode(w, extblock{ Header: b.header, Txs: b.transactions, @@ -274,7 +274,7 @@ func (b *StorageBlock) DecodeRLP(s *rlp.Stream) error { return nil } -func (b StorageBlock) EncodeRLP(w io.Writer) error { +func (b *StorageBlock) EncodeRLP(w io.Writer) error { return rlp.Encode(w, storageblock{ Header: b.header, Txs: b.transactions, diff --git a/crypto/curve.go b/crypto/curve.go index 841766a30..48f3f5e9c 100644 --- a/crypto/curve.go +++ b/crypto/curve.go @@ -60,7 +60,14 @@ type BitCurve struct { } func (BitCurve *BitCurve) Params() *elliptic.CurveParams { - return &elliptic.CurveParams{BitCurve.P, BitCurve.N, BitCurve.B, BitCurve.Gx, BitCurve.Gy, BitCurve.BitSize} + return &elliptic.CurveParams{ + P: BitCurve.P, + N: BitCurve.N, + B: BitCurve.B, + Gx: BitCurve.Gx, + Gy: BitCurve.Gy, + BitSize: BitCurve.BitSize, + } } // IsOnBitCurve returns true if the given (x,y) lies on the BitCurve. diff --git a/eth/backend.go b/eth/backend.go index 4bc00edde..dc592e7fc 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -45,6 +45,7 @@ import ( "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/nat" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/whisper" ) @@ -80,6 +81,7 @@ type Config struct { BlockChainVersion int SkipBcVersionCheck bool // e.g. blockchain export + DatabaseCache int DataDir string LogFile string @@ -261,7 +263,7 @@ func New(config *Config) (*Ethereum, error) { newdb := config.NewDB if newdb == nil { - newdb = func(path string) (common.Database, error) { return ethdb.NewLDBDatabase(path) } + newdb = func(path string) (common.Database, error) { return ethdb.NewLDBDatabase(path, config.DatabaseCache) } } blockDb, err := newdb(filepath.Join(config.DataDir, "blockchain")) if err != nil { @@ -367,6 +369,13 @@ func New(config *Config) (*Ethereum, error) { eth.miner = miner.New(eth, eth.EventMux(), eth.pow) eth.miner.SetGasPrice(config.GasPrice) + + extra := config.Name + if uint64(len(extra)) > params.MaximumExtraDataSize.Uint64() { + extra = extra[:params.MaximumExtraDataSize.Uint64()] + } + eth.miner.SetExtra([]byte(extra)) + if config.Shh { eth.whisper = whisper.New() eth.shhVersionId = int(eth.whisper.Version()) diff --git a/eth/handler.go b/eth/handler.go index f427854ac..2bd369901 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -95,6 +95,7 @@ func NewProtocolManager(networkId int, mux *event.TypeMux, txpool txPool, pow po newPeerCh: make(chan *peer, 1), txsyncCh: make(chan *txsync), quitSync: make(chan struct{}), + netId: networkId, } // Initiate a sub-protocol for every implemented version we can handle manager.SubProtocols = make([]p2p.Protocol, len(ProtocolVersions)) diff --git a/eth/protocol.go b/eth/protocol.go index 0bc845660..b8c9b50d0 100644 --- a/eth/protocol.go +++ b/eth/protocol.go @@ -30,7 +30,7 @@ var ProtocolVersions = []uint{61, 60} var ProtocolLengths = []uint64{9, 8} const ( - NetworkId = 0 + NetworkId = 1 ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message ) diff --git a/eth/protocol_test.go b/eth/protocol_test.go index c01f59691..a24d98f69 100644 --- a/eth/protocol_test.go +++ b/eth/protocol_test.go @@ -60,7 +60,7 @@ func TestStatusMsgErrors(t *testing.T) { }, { code: StatusMsg, data: statusData{uint32(ProtocolVersions[0]), 999, td, currentBlock, genesis}, - wantError: errResp(ErrNetworkIdMismatch, "999 (!= 0)"), + wantError: errResp(ErrNetworkIdMismatch, "999 (!= 1)"), }, { code: StatusMsg, data: statusData{uint32(ProtocolVersions[0]), NetworkId, td, currentBlock, common.Hash{3}}, @@ -184,7 +184,7 @@ func newProtocolManagerForTesting(txAdded chan<- []*types.Transaction) *Protocol em = new(event.TypeMux) chain, _ = core.NewChainManager(db, db, db, core.FakePow{}, em) txpool = &fakeTxPool{added: txAdded} - pm = NewProtocolManager(0, em, txpool, core.FakePow{}, chain) + pm = NewProtocolManager(NetworkId, em, txpool, core.FakePow{}, chain) ) pm.Start() return pm diff --git a/ethdb/database.go b/ethdb/database.go index c93344409..ace56c6c7 100644 --- a/ethdb/database.go +++ b/ethdb/database.go @@ -17,12 +17,12 @@ package ethdb import ( + "path/filepath" "strconv" "strings" "sync" "time" - "github.com/ethereum/go-ethereum/compression/rle" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/metrics" @@ -36,6 +36,14 @@ import ( var OpenFileLimit = 64 +// cacheRatio specifies how the total alloted cache is distributed between the +// various system databases. +var cacheRatio = map[string]float64{ + "blockchain": 1.0 / 13.0, + "extra": 2.0 / 13.0, + "state": 10.0 / 13.0, +} + type LDBDatabase struct { fn string // filename for reporting db *leveldb.DB // LevelDB instance @@ -57,14 +65,24 @@ type LDBDatabase struct { // NewLDBDatabase returns a LevelDB wrapped object. LDBDatabase does not persist data by // it self but requires a background poller which syncs every X. `Flush` should be called // when data needs to be stored and written to disk. -func NewLDBDatabase(file string) (*LDBDatabase, error) { - // Open the db - db, err := leveldb.OpenFile(file, &opt.Options{OpenFilesCacheCapacity: OpenFileLimit}) - // check for corruption and attempt to recover - if _, iscorrupted := err.(*errors.ErrCorrupted); iscorrupted { +func NewLDBDatabase(file string, cache int) (*LDBDatabase, error) { + // Calculate the cache allowance for this particular database + cache = int(float64(cache) * cacheRatio[filepath.Base(file)]) + if cache < 16 { + cache = 16 + } + glog.V(logger.Info).Infof("Alloted %dMB cache to %s", cache, file) + + // Open the db and recover any potential corruptions + db, err := leveldb.OpenFile(file, &opt.Options{ + OpenFilesCacheCapacity: OpenFileLimit, + BlockCacheCapacity: cache / 2 * opt.MiB, + WriteBuffer: cache / 4 * opt.MiB, // Two of these are used internally + }) + if _, corrupted := err.(*errors.ErrCorrupted); corrupted { db, err = leveldb.RecoverFile(file, nil) } - // (re) check for errors and abort if opening of the db failed + // (Re)check for errors and abort if opening of the db failed if err != nil { return nil, err } @@ -81,12 +99,12 @@ func (self *LDBDatabase) Put(key []byte, value []byte) error { defer self.putTimer.UpdateSince(time.Now()) } // Generate the data to write to disk, update the meter and write - dat := rle.Compress(value) + //value = rle.Compress(value) if self.writeMeter != nil { - self.writeMeter.Mark(int64(len(dat))) + self.writeMeter.Mark(int64(len(value))) } - return self.db.Put(key, dat, nil) + return self.db.Put(key, value, nil) } // Get returns the given key if it's present. @@ -107,7 +125,8 @@ func (self *LDBDatabase) Get(key []byte) ([]byte, error) { if self.readMeter != nil { self.readMeter.Mark(int64(len(dat))) } - return rle.Decompress(dat) + return dat, nil + //return rle.Decompress(dat) } // Delete deletes the key from the queue and database diff --git a/ethdb/database_test.go b/ethdb/database_test.go index 2465036aa..ae4906166 100644 --- a/ethdb/database_test.go +++ b/ethdb/database_test.go @@ -28,8 +28,7 @@ func newDb() *LDBDatabase { if common.FileExist(file) { os.RemoveAll(file) } - - db, _ := NewLDBDatabase(file) + db, _ := NewLDBDatabase(file, 0) return db } diff --git a/jsre/ethereum_js.go b/jsre/ethereum_js.go index 01a9b5da6..27dbed24c 100644 --- a/jsre/ethereum_js.go +++ b/jsre/ethereum_js.go @@ -373,10 +373,10 @@ var formatInputBytes = function (value) { * @returns {SolidityParam} */ var formatInputDynamicBytes = function (value) { - value = utils.toHex(value).substr(2); - var l = Math.floor((value.length + 63) / 64); - var result = utils.padRight(value, l * 64); - var length = Math.floor(value.length / 2); + var result = utils.toHex(value).substr(2); + var length = result.length / 2; + var l = Math.floor((result.length + 63) / 64); + var result = utils.padRight(result, l * 64); return new SolidityParam(formatInputInt(length).value + result, 32); }; @@ -389,9 +389,10 @@ var formatInputDynamicBytes = function (value) { */ var formatInputString = function (value) { var result = utils.fromAscii(value).substr(2); + var length = result.length / 2; var l = Math.floor((result.length + 63) / 64); result = utils.padRight(result, l * 64); - return new SolidityParam(formatInputInt(value.length).value + result, 32); + return new SolidityParam(formatInputInt(length).value + result, 32); }; /** @@ -996,6 +997,7 @@ var padRight = function (string, chars, sign) { /** * Should be called to get sting from it's hex representation + * TODO: it should be called toUTF8 * * @method toAscii * @param {String} string in hex @@ -1013,7 +1015,7 @@ var toAscii = function(hex) { str += String.fromCharCode(code); } - return str; + return decodeURIComponent(escape(str)); }; /** @@ -1024,6 +1026,7 @@ var toAscii = function(hex) { * @returns {String} hex representation of input string */ var toHexNative = function(str) { + str = unescape(encodeURIComponent(str)); var hex = ""; for(var i = 0; i < str.length; i++) { var n = str.charCodeAt(i).toString(16); @@ -1417,7 +1420,7 @@ module.exports = { },{"bignumber.js":"bignumber.js"}],8:[function(require,module,exports){ module.exports={ - "version": "0.8.1" + "version": "0.9.1" } },{}],9:[function(require,module,exports){ @@ -1524,6 +1527,9 @@ web3.setProvider = function (provider) { this.currentProvider = provider; RequestManager.getInstance().setProvider(provider); }; +web3.isConnected = function(){ + return (this.currentProvider && this.currentProvider.isConnected()); +}; web3.reset = function () { RequestManager.getInstance().reset(); c.defaultBlock = 'latest'; @@ -1594,7 +1600,7 @@ setupMethods(web3.shh, shh.methods); module.exports = web3; -},{"./utils/config":5,"./utils/sha3":6,"./utils/utils":7,"./version.json":8,"./web3/batch":11,"./web3/db":13,"./web3/eth":15,"./web3/filter":17,"./web3/formatters":18,"./web3/method":23,"./web3/net":25,"./web3/property":26,"./web3/requestmanager":28,"./web3/shh":29,"./web3/watches":31}],10:[function(require,module,exports){ +},{"./utils/config":5,"./utils/sha3":6,"./utils/utils":7,"./version.json":8,"./web3/batch":11,"./web3/db":13,"./web3/eth":15,"./web3/filter":17,"./web3/formatters":18,"./web3/method":24,"./web3/net":26,"./web3/property":27,"./web3/requestmanager":28,"./web3/shh":29,"./web3/watches":31}],10:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1639,7 +1645,6 @@ AllSolidityEvents.prototype.encode = function (options) { result[f] = formatters.inputBlockNumberFormatter(options[f]); }); - result.topics = [null, null, null, null, null]; // match all topics result.address = this._address; return result; @@ -1701,6 +1706,8 @@ module.exports = AllSolidityEvents; */ var RequestManager = require('./requestmanager'); +var Jsonrpc = require('./jsonrpc'); +var errors = require('./errors'); var Batch = function () { this.requests = []; @@ -1727,11 +1734,14 @@ Batch.prototype.execute = function () { results = results || []; requests.map(function (request, index) { return results[index] || {}; - }).map(function (result, index) { - return requests[index].format ? requests[index].format(result.result) : result.result; }).forEach(function (result, index) { if (requests[index].callback) { - requests[index].callback(err, result); + + if (!Jsonrpc.getInstance().isValidResponse(result)) { + return requests[index].callback(errors.InvalidResponse(result)); + } + + requests[index].callback(null, (requests[index].format ? requests[index].format(result.result) : result.result)); } }); }); @@ -1740,7 +1750,7 @@ Batch.prototype.execute = function () { module.exports = Batch; -},{"./requestmanager":28}],12:[function(require,module,exports){ +},{"./errors":14,"./jsonrpc":23,"./requestmanager":28}],12:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -1848,28 +1858,42 @@ var contract = function (abi) { * @returns {Undefined} */ var checkForContractAddress = function(contract, abi, callback){ - var count = 0; + var count = 0, + callbackFired = false; // wait for receipt var filter = web3.eth.filter('latest', function(e){ - if(!e) { + if(!e && !callbackFired) { count++; // console.log('Checking for contract address', count); // stop watching after 50 blocks (timeout) if(count > 50) { + + filter.stopWatching(); + callbackFired = true; + if(callback) - callback(new Error('Contract couldn\'t be deployed')); + callback(new Error('Contract transaction couldn\'t be found after 50 blocks')); + else + throw new Error('Contract transaction couldn\'t be found after 50 blocks'); - filter.stopWatching(); } else { web3.eth.getTransactionReceipt(contract.transactionHash, function(e, receipt){ - if(receipt) { + if(receipt && !callbackFired) { web3.eth.getCode(receipt.contractAddress, function(e, code){ + /*jshint maxcomplexity: 5 */ + + if(callbackFired) + return; + + filter.stopWatching(); + callbackFired = true; + if(code.length > 2) { // console.log('Contract code deployed!'); @@ -1880,14 +1904,16 @@ var checkForContractAddress = function(contract, abi, callback){ addFunctionsToContract(contract, abi); addEventsToContract(contract, abi); + // call callback for the second time if(callback) callback(null, contract); - } else if(callback) { - callback(new Error('The contract code couldn\'t be stored')); + } else { + if(callback) + callback(new Error('The contract code couldn\'t be stored, please check your gas amount.')); + else + throw new Error('The contract code couldn\'t be stored, please check your gas amount.'); } - - filter.stopWatching(); }); } }); @@ -1949,6 +1975,10 @@ ContractFactory.prototype.new = function () { } else { // add the transaction hash contract.transactionHash = hash; + + // call callback for the first time + callback(null, contract); + checkForContractAddress(contract, _this.abi, callback); } }); @@ -2057,7 +2087,7 @@ module.exports = { methods: methods }; -},{"./method":23}],14:[function(require,module,exports){ +},{"./method":24}],14:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2091,7 +2121,7 @@ module.exports = { return new Error('Providor not set or invalid'); }, InvalidResponse: function (result){ - var message = !!result && !!result.error && !!result.error.message ? result.error.message : 'Invalid JSON RPC response'; + var message = !!result && !!result.error && !!result.error.message ? result.error.message : 'Invalid JSON RPC response: '+ result; return new Error(message); } }; @@ -2271,7 +2301,7 @@ var sendRawTransaction = new Method({ name: 'sendRawTransaction', call: 'eth_sendRawTransaction', params: 1, - inputFormatter: [] + inputFormatter: [null] }); var sendTransaction = new Method({ @@ -2390,7 +2420,7 @@ module.exports = { }; -},{"../utils/utils":7,"./formatters":18,"./method":23,"./property":26}],16:[function(require,module,exports){ +},{"../utils/utils":7,"./formatters":18,"./method":24,"./property":27}],16:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -2692,9 +2722,11 @@ var getLogsAtStart = function(self, callback){ callback(err); } - messages.forEach(function (message) { - callback(null, message); - }); + if(utils.isArray(messages)) { + messages.forEach(function (message) { + callback(null, message); + }); + } }); } }; @@ -3314,12 +3346,11 @@ module.exports = SolidityFunction; * Marek Kotewicz <marek@ethdev.com> * Marian Oancea <marian@ethdev.com> * Fabian Vogelsteller <fabian@ethdev.com> - * @date 2014 + * @date 2015 */ "use strict"; -// resolves the problem for electron/atom shell environments, which use node integration, but have no process variable available var XMLHttpRequest = (typeof window !== 'undefined' && window.XMLHttpRequest) ? window.XMLHttpRequest : require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line var errors = require('./errors'); @@ -3327,6 +3358,25 @@ var HttpProvider = function (host) { this.host = host || 'http://localhost:8545'; }; +HttpProvider.prototype.isConnected = function() { + var request = new XMLHttpRequest(); + + request.open('POST', this.host, false); + request.setRequestHeader('Content-type','application/json'); + + try { + request.send(JSON.stringify({ + id: 9999999999, + jsonrpc: '2.0', + method: 'net_listening', + params: [] + })); + return true; + } catch(e) { + return false; + } +}; + HttpProvider.prototype.send = function (payload) { var request = new XMLHttpRequest(); @@ -3351,7 +3401,7 @@ HttpProvider.prototype.send = function (payload) { try { result = JSON.parse(result); } catch(e) { - throw errors.InvalidResponse(result); + throw errors.InvalidResponse(request.responseText); } return result; @@ -3367,7 +3417,7 @@ HttpProvider.prototype.sendAsync = function (payload, callback) { try { result = JSON.parse(result); } catch(e) { - error = errors.InvalidResponse(result); + error = errors.InvalidResponse(request.responseText); } callback(error, result); @@ -3514,6 +3564,219 @@ module.exports = ICAP; You should have received a copy of the GNU Lesser General Public License along with ethereum.js. If not, see <http://www.gnu.org/licenses/>. */ +/** @file ipcprovider.js + * @authors: + * Fabian Vogelsteller <fabian@ethdev.com> + * @date 2015 + */ + +"use strict"; + +var utils = require('../utils/utils'); +var errors = require('./errors'); + +var errorTimeout = '{"jsonrpc": "2.0", "error": {"code": -32603, "message": "IPC Request timed out for method \'__method__\'"}, "id": "__id__"}'; + + +var IpcProvider = function (path, net) { + var _this = this; + this.responseCallbacks = {}; + this.path = path; + + net = net || require('net'); + + this.connection = net.connect({path: this.path}); + + this.connection.on('error', function(e){ + console.error('IPC Connection Error', e); + _this._timeout(); + }); + + this.connection.on('end', function(){ + _this._timeout(); + }); + + + // LISTEN FOR CONNECTION RESPONSES + this.connection.on('data', function(data) { + /*jshint maxcomplexity: 6 */ + + _this._parseResponse(data.toString()).forEach(function(result){ + + var id = null; + + // get the id which matches the returned id + if(utils.isArray(result)) { + result.forEach(function(load){ + if(_this.responseCallbacks[load.id]) + id = load.id; + }); + } else { + id = result.id; + } + + // fire the callback + if(_this.responseCallbacks[id]) { + _this.responseCallbacks[id](null, result); + delete _this.responseCallbacks[id]; + } + }); + }); +}; + +/** +Will parse the response and make an array out of it. + +@method _parseResponse +@param {String} data +*/ +IpcProvider.prototype._parseResponse = function(data) { + var _this = this, + returnValues = []; + + // DE-CHUNKER + var dechunkedData = data + .replace(/\}\{/g,'}|--|{') // }{ + .replace(/\}\]\[\{/g,'}]|--|[{') // }][{ + .replace(/\}\[\{/g,'}|--|[{') // }[{ + .replace(/\}\]\{/g,'}]|--|{') // }]{ + .split('|--|'); + + dechunkedData.forEach(function(data){ + + // prepend the last chunk + if(_this.lastChunk) + data = _this.lastChunk + data; + + var result = null; + + try { + result = JSON.parse(data); + + } catch(e) { + + _this.lastChunk = data; + + // start timeout to cancel all requests + clearTimeout(_this.lastChunkTimeout); + _this.lastChunkTimeout = setTimeout(function(){ + _this.timeout(); + throw errors.InvalidResponse(data); + }, 1000 * 15); + + return; + } + + // cancel timeout and set chunk to null + clearTimeout(_this.lastChunkTimeout); + _this.lastChunk = null; + + if(result) + returnValues.push(result); + }); + + return returnValues; +}; + + +/** +Get the adds a callback to the responseCallbacks object, +which will be called if a response matching the response Id will arrive. + +@method _addResponseCallback +*/ +IpcProvider.prototype._addResponseCallback = function(payload, callback) { + var id = payload.id || payload[0].id; + var method = payload.method || payload[0].method; + + this.responseCallbacks[id] = callback; + this.responseCallbacks[id].method = method; +}; + +/** +Timeout all requests when the end/error event is fired + +@method _timeout +*/ +IpcProvider.prototype._timeout = function() { + for(var key in this.responseCallbacks) { + if(this.responseCallbacks.hasOwnProperty(key)){ + this.responseCallbacks[key](errorTimeout.replace('__id__', key).replace('__method__', this.responseCallbacks[key].method)); + delete this.responseCallbacks[key]; + } + } +}; + + +/** +Check if the current connection is still valid. + +@method isConnected +*/ +IpcProvider.prototype.isConnected = function() { + var _this = this; + + // try reconnect, when connection is gone + if(!_this.connection.writable) + _this.connection.connect({path: _this.path}); + + return !!this.connection.writable; +}; + +IpcProvider.prototype.send = function (payload) { + + if(this.connection.writeSync) { + var result; + + // try reconnect, when connection is gone + if(!this.connection.writable) + this.connection.connect({path: this.path}); + + var data = this.connection.writeSync(JSON.stringify(payload)); + + try { + result = JSON.parse(data); + } catch(e) { + throw errors.InvalidResponse(data); + } + + return result; + + } else { + throw new Error('You tried to send "'+ payload.method +'" synchronously. Synchronous requests are not supported by the IPC provider.'); + } +}; + +IpcProvider.prototype.sendAsync = function (payload, callback) { + // try reconnect, when connection is gone + if(!this.connection.writable) + this.connection.connect({path: this.path}); + + + this.connection.write(JSON.stringify(payload)); + this._addResponseCallback(payload, callback); +}; + +module.exports = IpcProvider; + + +},{"../utils/utils":7,"./errors":14,"net":32}],23:[function(require,module,exports){ +/* + This file is part of ethereum.js. + + ethereum.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + ethereum.js is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with ethereum.js. If not, see <http://www.gnu.org/licenses/>. +*/ /** @file jsonrpc.js * @authors: * Marek Kotewicz <marek@ethdev.com> @@ -3590,7 +3853,7 @@ Jsonrpc.prototype.toBatchPayload = function (messages) { module.exports = Jsonrpc; -},{}],23:[function(require,module,exports){ +},{}],24:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3687,7 +3950,7 @@ Method.prototype.formatInput = function (args) { * @return {Object} */ Method.prototype.formatOutput = function (result) { - return this.outputFormatter && result !== null ? this.outputFormatter(result) : result; + return this.outputFormatter && result ? this.outputFormatter(result) : result; }; /** @@ -3764,7 +4027,7 @@ Method.prototype.send = function () { module.exports = Method; -},{"../utils/utils":7,"./errors":14,"./requestmanager":28}],24:[function(require,module,exports){ +},{"../utils/utils":7,"./errors":14,"./requestmanager":28}],25:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3812,7 +4075,7 @@ var abi = [ module.exports = contract(abi).at(address); -},{"./contract":12}],25:[function(require,module,exports){ +},{"./contract":12}],26:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3862,7 +4125,7 @@ module.exports = { }; -},{"../utils/utils":7,"./property":26}],26:[function(require,module,exports){ +},{"../utils/utils":7,"./property":27}],27:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -3887,6 +4150,7 @@ module.exports = { */ var RequestManager = require('./requestmanager'); +var utils = require('../utils/utils'); var Property = function (options) { this.name = options.name; @@ -3919,6 +4183,19 @@ Property.prototype.formatOutput = function (result) { }; /** + * Should be used to extract callback from array of arguments. Modifies input param + * + * @method extractCallback + * @param {Array} arguments + * @return {Function|Null} callback, if exists + */ +Property.prototype.extractCallback = function (args) { + if (utils.isFunction(args[args.length - 1])) { + return args.pop(); // modify the args array! + } +}; + +/** * Should attach function to method * * @method attachToObject @@ -3944,7 +4221,10 @@ Property.prototype.attachToObject = function (obj) { return prefix + name.charAt(0).toUpperCase() + name.slice(1); }; - obj[toAsyncName('get', name)] = this.getAsync.bind(this); + var func = this.getAsync.bind(this); + func.request = this.request.bind(this); + + obj[toAsyncName('get', name)] = func; }; /** @@ -3977,45 +4257,27 @@ Property.prototype.getAsync = function (callback) { }); }; -module.exports = Property; - - -},{"./requestmanager":28}],27:[function(require,module,exports){ -/* - This file is part of ethereum.js. - - ethereum.js is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - ethereum.js is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with ethereum.js. If not, see <http://www.gnu.org/licenses/>. -*/ -/** @file qtsync.js - * @authors: - * Marek Kotewicz <marek@ethdev.com> - * Marian Oancea <marian@ethdev.com> - * @date 2014 +/** + * Should be called to create pure JSONRPC request which can be used in batch request + * + * @method request + * @param {...} params + * @return {Object} jsonrpc request */ - -var QtSyncProvider = function () { -}; - -QtSyncProvider.prototype.send = function (payload) { - var result = navigator.qt.callMethod(JSON.stringify(payload)); - return JSON.parse(result); +Property.prototype.request = function () { + var payload = { + method: this.getter, + params: [], + callback: this.extractCallback(Array.prototype.slice.call(arguments)) + }; + payload.format = this.formatOutput.bind(this); + return payload; }; -module.exports = QtSyncProvider; +module.exports = Property; -},{}],28:[function(require,module,exports){ +},{"../utils/utils":7,"./requestmanager":28}],28:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -4280,7 +4542,7 @@ RequestManager.prototype.poll = function () { module.exports = RequestManager; -},{"../utils/config":5,"../utils/utils":7,"./errors":14,"./jsonrpc":22}],29:[function(require,module,exports){ +},{"../utils/config":5,"../utils/utils":7,"./errors":14,"./jsonrpc":23}],29:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -4350,7 +4612,7 @@ module.exports = { }; -},{"./formatters":18,"./method":23}],30:[function(require,module,exports){ +},{"./formatters":18,"./method":24}],30:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -4446,7 +4708,7 @@ var deposit = function (from, address, value, client, callback) { module.exports = transfer; -},{"../web3":9,"./contract":12,"./icap":21,"./namereg":24}],31:[function(require,module,exports){ +},{"../web3":9,"./contract":12,"./icap":21,"./namereg":25}],31:[function(require,module,exports){ /* This file is part of ethereum.js. @@ -4562,7 +4824,7 @@ module.exports = { }; -},{"./method":23}],32:[function(require,module,exports){ +},{"./method":24}],32:[function(require,module,exports){ },{}],33:[function(require,module,exports){ ;(function (root, factory) { @@ -5944,8 +6206,10 @@ module.exports = BigNumber; // jshint ignore:line },{}],"web3":[function(require,module,exports){ var web3 = require('./lib/web3'); + web3.providers.HttpProvider = require('./lib/web3/httpprovider'); -web3.providers.QtSyncProvider = require('./lib/web3/qtsync'); +web3.providers.IpcProvider = require('./lib/web3/ipcprovider'); + web3.eth.contract = require('./lib/web3/contract'); web3.eth.namereg = require('./lib/web3/namereg'); web3.eth.sendIBANTransaction = require('./lib/web3/transfer'); @@ -5958,6 +6222,6 @@ if (typeof window !== 'undefined' && typeof window.web3 === 'undefined') { module.exports = web3; -},{"./lib/web3":9,"./lib/web3/contract":12,"./lib/web3/httpprovider":20,"./lib/web3/namereg":24,"./lib/web3/qtsync":27,"./lib/web3/transfer":30}]},{},["web3"]) +},{"./lib/web3":9,"./lib/web3/contract":12,"./lib/web3/httpprovider":20,"./lib/web3/ipcprovider":22,"./lib/web3/namereg":25,"./lib/web3/transfer":30}]},{},["web3"]) //# sourceMappingURL=web3-light.js.map ` diff --git a/params/protocol_params.go b/params/protocol_params.go index baa1b63a9..b1a6757b1 100755 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -22,49 +22,51 @@ package params import "math/big" var ( - MaximumExtraDataSize = big.NewInt(1024) // Maximum size extra data may be after Genesis. - ExpByteGas = big.NewInt(10) // Times ceil(log256(exponent)) for the EXP instruction. - SloadGas = big.NewInt(50) // Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added. - CallValueTransferGas = big.NewInt(9000) // Paid for CALL when the value transfor is non-zero. - CallNewAccountGas = big.NewInt(25000) // Paid for CALL when the destination address didn't exist prior. - TxGas = big.NewInt(21000) // Per transaction. NOTE: Not payable on data of calls between transactions. - TxDataZeroGas = big.NewInt(4) // Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions. - GenesisGasLimit = big.NewInt(3141592) // Gas limit of the Genesis block. - DifficultyBoundDivisor = big.NewInt(2048) // The bound divisor of the difficulty, used in the update calculations. - QuadCoeffDiv = big.NewInt(512) // Divisor for the quadratic particle of the memory cost equation. - GenesisDifficulty = big.NewInt(131072) // Difficulty of the Genesis block. - DurationLimit = big.NewInt(8) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not. - SstoreSetGas = big.NewInt(20000) // Once per SLOAD operation. - LogDataGas = big.NewInt(8) // Per byte in a LOG* operation's data. - CallStipend = big.NewInt(2300) // Free gas given at beginning of call. - EcrecoverGas = big.NewInt(3000) // - Sha256WordGas = big.NewInt(12) // - MinGasLimit = big.NewInt(125000) // Minimum the gas limit may ever be. - Sha3Gas = big.NewInt(30) // Once per SHA3 operation. - Sha256Gas = big.NewInt(60) // - IdentityWordGas = big.NewInt(3) // - Sha3WordGas = big.NewInt(6) // Once per word of the SHA3 operation's data. - SstoreResetGas = big.NewInt(5000) // Once per SSTORE operation if the zeroness changes from zero. - SstoreClearGas = big.NewInt(5000) // Once per SSTORE operation if the zeroness doesn't change. - SstoreRefundGas = big.NewInt(15000) // Once per SSTORE operation if the zeroness changes to zero. - JumpdestGas = big.NewInt(1) // Refunded gas, once per SSTORE operation if the zeroness changes to zero. - IdentityGas = big.NewInt(15) // - GasLimitBoundDivisor = big.NewInt(1024) // The bound divisor of the gas limit, used in update calculations. - EpochDuration = big.NewInt(30000) // Duration between proof-of-work epochs. - CallGas = big.NewInt(40) // Once per CALL operation & message call transaction. - CreateDataGas = big.NewInt(200) // - Ripemd160Gas = big.NewInt(600) // - Ripemd160WordGas = big.NewInt(120) // - MinimumDifficulty = big.NewInt(131072) // The minimum that the difficulty may ever be. - CallCreateDepth = big.NewInt(1024) // Maximum depth of call/create stack. - ExpGas = big.NewInt(10) // Once per EXP instuction. - LogGas = big.NewInt(375) // Per LOG* operation. - CopyGas = big.NewInt(3) // - StackLimit = big.NewInt(1024) // Maximum size of VM stack allowed. - TierStepGas = big.NewInt(0) // Once per operation, for a selection of them. - LogTopicGas = big.NewInt(375) // Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas. - CreateGas = big.NewInt(32000) // Once per CREATE operation & contract-creation transaction. - SuicideRefundGas = big.NewInt(24000) // Refunded following a suicide operation. - MemoryGas = big.NewInt(3) // Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL. - TxDataNonZeroGas = big.NewInt(68) // Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions. + MaximumExtraDataSize = big.NewInt(32) // Maximum size extra data may be after Genesis. + ExpByteGas = big.NewInt(10) // Times ceil(log256(exponent)) for the EXP instruction. + SloadGas = big.NewInt(50) // Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added. + CallValueTransferGas = big.NewInt(9000) // Paid for CALL when the value transfor is non-zero. + CallNewAccountGas = big.NewInt(25000) // Paid for CALL when the destination address didn't exist prior. + TxGas = big.NewInt(21000) // Per transaction. NOTE: Not payable on data of calls between transactions. + TxDataZeroGas = big.NewInt(4) // Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions. + DifficultyBoundDivisor = big.NewInt(2048) // The bound divisor of the difficulty, used in the update calculations. + QuadCoeffDiv = big.NewInt(512) // Divisor for the quadratic particle of the memory cost equation. + GenesisDifficulty = big.NewInt(131072) // Difficulty of the Genesis block. + DurationLimit = big.NewInt(13) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not. + SstoreSetGas = big.NewInt(20000) // Once per SLOAD operation. + LogDataGas = big.NewInt(8) // Per byte in a LOG* operation's data. + CallStipend = big.NewInt(2300) // Free gas given at beginning of call. + EcrecoverGas = big.NewInt(3000) // + Sha256WordGas = big.NewInt(12) // + + MinGasLimit = big.NewInt(5000) // Minimum the gas limit may ever be. + GenesisGasLimit = big.NewInt(5000) // Gas limit of the Genesis block. + + Sha3Gas = big.NewInt(30) // Once per SHA3 operation. + Sha256Gas = big.NewInt(60) // + IdentityWordGas = big.NewInt(3) // + Sha3WordGas = big.NewInt(6) // Once per word of the SHA3 operation's data. + SstoreResetGas = big.NewInt(5000) // Once per SSTORE operation if the zeroness changes from zero. + SstoreClearGas = big.NewInt(5000) // Once per SSTORE operation if the zeroness doesn't change. + SstoreRefundGas = big.NewInt(15000) // Once per SSTORE operation if the zeroness changes to zero. + JumpdestGas = big.NewInt(1) // Refunded gas, once per SSTORE operation if the zeroness changes to zero. + IdentityGas = big.NewInt(15) // + GasLimitBoundDivisor = big.NewInt(1024) // The bound divisor of the gas limit, used in update calculations. + EpochDuration = big.NewInt(30000) // Duration between proof-of-work epochs. + CallGas = big.NewInt(40) // Once per CALL operation & message call transaction. + CreateDataGas = big.NewInt(200) // + Ripemd160Gas = big.NewInt(600) // + Ripemd160WordGas = big.NewInt(120) // + MinimumDifficulty = big.NewInt(131072) // The minimum that the difficulty may ever be. + CallCreateDepth = big.NewInt(1024) // Maximum depth of call/create stack. + ExpGas = big.NewInt(10) // Once per EXP instuction. + LogGas = big.NewInt(375) // Per LOG* operation. + CopyGas = big.NewInt(3) // + StackLimit = big.NewInt(1024) // Maximum size of VM stack allowed. + TierStepGas = big.NewInt(0) // Once per operation, for a selection of them. + LogTopicGas = big.NewInt(375) // Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas. + CreateGas = big.NewInt(32000) // Once per CREATE operation & contract-creation transaction. + SuicideRefundGas = big.NewInt(24000) // Refunded following a suicide operation. + MemoryGas = big.NewInt(3) // Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL. + TxDataNonZeroGas = big.NewInt(68) // Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions. ) diff --git a/rpc/api/miner.go b/rpc/api/miner.go index d134f1a55..3c3d1ee0b 100644 --- a/rpc/api/miner.go +++ b/rpc/api/miner.go @@ -17,9 +17,12 @@ package api import ( + "fmt" + "github.com/ethereum/ethash" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/eth" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc/codec" "github.com/ethereum/go-ethereum/rpc/shared" ) @@ -122,6 +125,11 @@ func (self *minerApi) SetExtra(req *shared.Request) (interface{}, error) { if err := self.codec.Decode(req.Params, &args); err != nil { return nil, err } + + if uint64(len(args.Data)) > params.MaximumExtraDataSize.Uint64()*2 { + return false, fmt.Errorf("extra datasize can be no longer than %v bytes", params.MaximumExtraDataSize) + } + self.ethereum.Miner().SetExtra([]byte(args.Data)) return true, nil } diff --git a/tests/block_test.go b/tests/block_test.go index f80e1f377..6bb123184 100644 --- a/tests/block_test.go +++ b/tests/block_test.go @@ -17,10 +17,18 @@ package tests import ( + "math/big" "path/filepath" "testing" + + "github.com/ethereum/go-ethereum/core" ) +func init() { + // XXX remove me when block tests have been updated + core.BlockReward = big.NewInt(1.5e+18) +} + func TestBcValidBlockTests(t *testing.T) { err := RunBlockTest(filepath.Join(blockTestDir, "bcValidBlockTest.json"), BlockSkipTests) if err != nil { diff --git a/trie/cache.go b/trie/cache.go index d661648b4..2705b0e45 100644 --- a/trie/cache.go +++ b/trie/cache.go @@ -17,7 +17,6 @@ package trie import ( - "github.com/ethereum/go-ethereum/compression/rle" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/logger/glog" "github.com/syndtr/goleveldb/leveldb" @@ -49,7 +48,8 @@ func (self *Cache) Get(key []byte) []byte { func (self *Cache) Put(key []byte, data []byte) { // write the data to the ldb batch - self.batch.Put(key, rle.Compress(data)) + //self.batch.Put(key, rle.Compress(data)) + self.batch.Put(key, data) self.store[string(key)] = data } diff --git a/xeth/xeth.go b/xeth/xeth.go index 68d760ccb..63826a334 100644 --- a/xeth/xeth.go +++ b/xeth/xeth.go @@ -123,7 +123,7 @@ func New(ethereum *eth.Ethereum, frontend Frontend) *XEth { if frontend == nil { xeth.frontend = dummyFrontend{} } - xeth.state = NewState(xeth, xeth.backend.ChainManager().TransState()) + xeth.state = NewState(xeth, xeth.backend.ChainManager().State()) go xeth.start() go xeth.filterManager.Start() |