aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeterminant <[email protected]>2019-09-26 16:16:56 -0400
committerDeterminant <[email protected]>2019-09-26 16:16:56 -0400
commita96fc7a942fb6f0a9da5b5bf9c84a98af42a24dc (patch)
tree8cb685aa6df55f15758e93ffe24b6c5d075859a5
parent2e0b38c332a3ab4e11b97a38ff6d8427a3d96215 (diff)
remove 1s limit from block generation; more API
-rw-r--r--consensus/dummy/consensus.go13
-rw-r--r--coreth.go16
-rw-r--r--eth/backend.go8
-rw-r--r--examples/chain/main.go115
-rw-r--r--miner/miner.go5
-rw-r--r--miner/worker.go22
-rw-r--r--params/protocol_params.go23
7 files changed, 138 insertions, 64 deletions
diff --git a/consensus/dummy/consensus.go b/consensus/dummy/consensus.go
index 0fbc674..c9bbb90 100644
--- a/consensus/dummy/consensus.go
+++ b/consensus/dummy/consensus.go
@@ -8,6 +8,7 @@ import (
"runtime"
"time"
+ myparams "github.com/ava-labs/coreth/params"
"github.com/ava-labs/go-ethereum/common"
"github.com/ava-labs/go-ethereum/consensus"
"github.com/ava-labs/go-ethereum/core/state"
@@ -24,6 +25,7 @@ type OnAPIsCallbackType = func(consensus.ChainReader) []rpc.API
type ConsensusCallbacks struct {
OnSeal func(*types.Block) error
+ OnSealHash func(*types.Header)
OnAPIs OnAPIsCallbackType
OnFinalize OnFinalizeCallbackType
OnFinalizeAndAssemble OnFinalizeAndAssembleCallbackType
@@ -54,8 +56,8 @@ var (
// modified from consensus.go
func (self *DummyEngine) verifyHeader(chain consensus.ChainReader, header, parent *types.Header, uncle bool, seal bool) error {
// Ensure that the header's extra-data section is of a reasonable size
- if uint64(len(header.Extra)) > params.MaximumExtraDataSize {
- return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), params.MaximumExtraDataSize)
+ if uint64(len(header.Extra)) > myparams.MaximumExtraDataSize {
+ return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), myparams.MaximumExtraDataSize)
}
// Verify the header's timestamp
if !uncle {
@@ -63,7 +65,8 @@ func (self *DummyEngine) verifyHeader(chain consensus.ChainReader, header, paren
return consensus.ErrFutureBlock
}
}
- if header.Time <= parent.Time {
+ //if header.Time <= parent.Time {
+ if header.Time < parent.Time {
return errZeroBlockTime
}
// Verify that the gas limit is <= 2^63-1
@@ -278,6 +281,10 @@ func (self *DummyEngine) Seal(chain consensus.ChainReader, block *types.Block, r
}
func (self *DummyEngine) SealHash(header *types.Header) (hash common.Hash) {
+ if self.cb.OnSealHash != nil {
+ self.cb.OnSealHash(header)
+ }
+
hasher := sha3.NewLegacyKeccak256()
rlp.Encode(hasher, []interface{}{
diff --git a/coreth.go b/coreth.go
index f3180e6..4bb0ae8 100644
--- a/coreth.go
+++ b/coreth.go
@@ -96,8 +96,20 @@ func (self *ETHChain) SetOnSeal(cb func(*types.Block) error) {
self.cb.OnSeal = cb
}
-func (self *ETHChain) SetOnSealMiner(cb func(*types.Block) error) {
- self.mcb.OnSeal = cb
+func (self *ETHChain) SetOnSealHash(cb func(*types.Header)) {
+ self.cb.OnSealHash = cb
+}
+
+func (self *ETHChain) SetOnSealFinish(cb func(*types.Block) error) {
+ self.mcb.OnSealFinish = cb
+}
+
+func (self *ETHChain) SetOnHeaderNew(cb func(*types.Header)) {
+ self.mcb.OnHeaderNew = cb
+}
+
+func (self *ETHChain) SetOnSealDrop(cb func(*types.Block)) {
+ self.mcb.OnSealDrop = cb
}
func (self *ETHChain) SetOnAPIs(cb dummy.OnAPIsCallbackType) {
diff --git a/eth/backend.go b/eth/backend.go
index b297b9b..4281d96 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -30,6 +30,7 @@ import (
"github.com/ava-labs/coreth/internal/ethapi"
"github.com/ava-labs/coreth/miner"
"github.com/ava-labs/coreth/node"
+ myparams "github.com/ava-labs/coreth/params"
"github.com/ava-labs/go-ethereum/accounts"
"github.com/ava-labs/go-ethereum/accounts/abi/bind"
"github.com/ava-labs/go-ethereum/common"
@@ -240,8 +241,8 @@ func makeExtraData(extra []byte) []byte {
runtime.GOOS,
})
}
- if uint64(len(extra)) > params.MaximumExtraDataSize {
- log.Warn("Miner extra data exceed limit", "extra", hexutil.Bytes(extra), "limit", params.MaximumExtraDataSize)
+ if uint64(len(extra)) > myparams.MaximumExtraDataSize {
+ log.Warn("Miner extra data exceed limit", "extra", hexutil.Bytes(extra), "limit", myparams.MaximumExtraDataSize)
extra = nil
}
return extra
@@ -441,7 +442,8 @@ func (s *Ethereum) StartMining(threads int) error {
// introduced to speed sync times.
atomic.StoreUint32(&s.protocolManager.acceptTxs, 1)
- go s.miner.Start(eb)
+ //go s.miner.Start(eb)
+ s.miner.Start(eb)
}
return nil
}
diff --git a/examples/chain/main.go b/examples/chain/main.go
index eddebd5..92350d3 100644
--- a/examples/chain/main.go
+++ b/examples/chain/main.go
@@ -13,8 +13,8 @@ import (
"github.com/ava-labs/go-ethereum/params"
"github.com/ava-labs/go-ethereum/rlp"
"math/big"
- //mrand "math/rand"
- "time"
+ "sync"
+ //"time"
)
func checkError(err error) {
@@ -30,6 +30,7 @@ type TestChain struct {
chain *coreth.ETHChain
parentBlock common.Hash
outBlockCh chan<- []byte
+ blockWait sync.WaitGroup
}
func (tc *TestChain) insertBlock(block *types.Block) {
@@ -50,7 +51,16 @@ func NewTestChain(name string, config *eth.Config,
outBlockCh: outBlockCh,
}
tc.insertBlock(tc.chain.GetGenesisBlock())
- tc.chain.SetOnSealMiner(func(block *types.Block) error {
+ tc.chain.SetOnHeaderNew(func(header *types.Header) {
+ hid := make([]byte, 32)
+ _, err := rand.Read(hid)
+ if err != nil {
+ panic("cannot generate hid")
+ }
+ header.Extra = append(header.Extra, hid...)
+ //fmt.Printf("%s\n", hexutil.Encode(header.Extra))
+ })
+ tc.chain.SetOnSealFinish(func(block *types.Block) error {
blkID := tc.blkCount
tc.blkCount++
if len(block.Uncles()) != 0 {
@@ -71,6 +81,7 @@ func NewTestChain(name string, config *eth.Config,
<-inAckCh
log.Info(fmt.Sprintf("%s: got ack", name))
}
+ tc.blockWait.Done()
return nil
})
go func() {
@@ -104,72 +115,37 @@ func (tc *TestChain) GenRandomTree(n int, max int) {
for i := 0; i < n; i++ {
nblocks := len(tc.blocks)
m := max
- if m < 0 {
+ if m < 0 || nblocks < m {
m = nblocks
}
pb, _ := rand.Int(rand.Reader, big.NewInt((int64)(m)))
pn := pb.Int64()
tc.parentBlock = tc.blocks[nblocks-1-(int)(pn)]
tc.chain.SetTail(tc.parentBlock)
+ tc.blockWait.Add(1)
tc.chain.GenBlock()
- time.Sleep(time.Second)
+ tc.blockWait.Wait()
}
}
-func main() {
- // configure the chain
- config := eth.DefaultConfig
- chainConfig := &params.ChainConfig{
- ChainID: big.NewInt(1),
- HomesteadBlock: big.NewInt(0),
- DAOForkBlock: big.NewInt(0),
- DAOForkSupport: true,
- EIP150Block: big.NewInt(0),
- EIP150Hash: common.HexToHash("0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0"),
- EIP155Block: big.NewInt(0),
- EIP158Block: big.NewInt(0),
- ByzantiumBlock: big.NewInt(0),
- ConstantinopleBlock: big.NewInt(0),
- PetersburgBlock: big.NewInt(0),
- IstanbulBlock: nil,
- Ethash: nil,
- }
-
- // configure the genesis block
- genBalance := big.NewInt(100000000000000000)
- genKey, _ := coreth.NewKey(rand.Reader)
-
- config.Genesis = &core.Genesis{
- Config: chainConfig,
- Nonce: 0,
- Number: 0,
- ExtraData: hexutil.MustDecode("0x00"),
- GasLimit: 100000000,
- Difficulty: big.NewInt(0),
- Alloc: core.GenesisAlloc{genKey.Address: {Balance: genBalance}},
- }
-
- // grab the control of block generation and disable auto uncle
- config.Miner.ManualMining = true
- config.Miner.DisableUncle = true
-
+func run(config *eth.Config, a1, a2, b1, b2 int) {
aliceBlk := make(chan []byte)
bobBlk := make(chan []byte)
aliceAck := make(chan struct{})
bobAck := make(chan struct{})
- alice := NewTestChain("alice", &config, bobBlk, aliceBlk, bobAck, aliceAck)
- bob := NewTestChain("bob", &config, aliceBlk, bobBlk, aliceAck, bobAck)
+ alice := NewTestChain("alice", config, bobBlk, aliceBlk, bobAck, aliceAck)
+ bob := NewTestChain("bob", config, aliceBlk, bobBlk, aliceAck, bobAck)
alice.Start()
bob.Start()
- alice.GenRandomTree(60, -1)
+ alice.GenRandomTree(a1, a2)
log.Info("alice finished generating the tree")
- time.Sleep(2 * time.Second)
+ //time.Sleep(1 * time.Second)
bob.outBlockCh = nil
- bob.GenRandomTree(60, 2)
+ bob.GenRandomTree(b1, b2)
//mrand.Shuffle(len(bob.blocks),
// func(i, j int) { bob.blocks[i], bob.blocks[j] = bob.blocks[j], bob.blocks[i] })
log.Info("bob finished generating the tree")
- time.Sleep(2 * time.Second)
+ //time.Sleep(1 * time.Second)
log.Info("bob sends out all its blocks")
for i := range bob.blocks {
serialized, err := rlp.EncodeToBytes(bob.chain.GetBlockByHash(bob.blocks[i]))
@@ -181,7 +157,7 @@ func main() {
log.Info(fmt.Sprintf("bob: got ack"))
}
log.Info("bob finished generating the tree")
- time.Sleep(2 * time.Second)
+ //time.Sleep(1 * time.Second)
log.Info("comparing two trees")
if len(alice.blocks) != len(bob.blocks) {
panic(fmt.Sprintf("mismatching tree size %d != %d", len(alice.blocks), len(bob.blocks)))
@@ -211,3 +187,44 @@ func main() {
alice.Stop()
bob.Stop()
}
+
+func main() {
+ // configure the chain
+ config := eth.DefaultConfig
+ chainConfig := &params.ChainConfig{
+ ChainID: big.NewInt(1),
+ HomesteadBlock: big.NewInt(0),
+ DAOForkBlock: big.NewInt(0),
+ DAOForkSupport: true,
+ EIP150Block: big.NewInt(0),
+ EIP150Hash: common.HexToHash("0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0"),
+ EIP155Block: big.NewInt(0),
+ EIP158Block: big.NewInt(0),
+ ByzantiumBlock: big.NewInt(0),
+ ConstantinopleBlock: big.NewInt(0),
+ PetersburgBlock: big.NewInt(0),
+ IstanbulBlock: nil,
+ Ethash: nil,
+ }
+
+ // configure the genesis block
+ genBalance := big.NewInt(100000000000000000)
+ genKey, _ := coreth.NewKey(rand.Reader)
+
+ config.Genesis = &core.Genesis{
+ Config: chainConfig,
+ Nonce: 0,
+ Number: 0,
+ ExtraData: hexutil.MustDecode("0x00"),
+ GasLimit: 100000000,
+ Difficulty: big.NewInt(0),
+ Alloc: core.GenesisAlloc{genKey.Address: {Balance: genBalance}},
+ }
+
+ // grab the control of block generation and disable auto uncle
+ config.Miner.ManualMining = true
+ config.Miner.DisableUncle = true
+
+ run(&config, 60, 1, 60, 1)
+ run(&config, 500, 10, 500, 5)
+}
diff --git a/miner/miner.go b/miner/miner.go
index 60a5d39..583e458 100644
--- a/miner/miner.go
+++ b/miner/miner.go
@@ -22,6 +22,7 @@ import (
"math/big"
"time"
+ myparams "github.com/ava-labs/coreth/params"
"github.com/ava-labs/go-ethereum/common"
"github.com/ava-labs/go-ethereum/common/hexutil"
"github.com/ava-labs/go-ethereum/consensus"
@@ -80,8 +81,8 @@ func (self *Miner) HashRate() uint64 {
}
func (self *Miner) SetExtra(extra []byte) error {
- if uint64(len(extra)) > params.MaximumExtraDataSize {
- return fmt.Errorf("Extra exceeds max length. %d > %v", len(extra), params.MaximumExtraDataSize)
+ if uint64(len(extra)) > myparams.MaximumExtraDataSize {
+ return fmt.Errorf("Extra exceeds max length. %d > %v", len(extra), myparams.MaximumExtraDataSize)
}
self.w.setExtra(extra)
return nil
diff --git a/miner/worker.go b/miner/worker.go
index 8dd2aff..11f3f71 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -26,7 +26,6 @@ import (
"sync"
"sync/atomic"
"time"
- //"fmt"
"github.com/ava-labs/go-ethereum/common"
"github.com/ava-labs/go-ethereum/consensus"
@@ -124,7 +123,9 @@ type intervalAdjust struct {
}
type MinerCallbacks struct {
- OnSeal func(*types.Block) error
+ OnSealFinish func(*types.Block) error
+ OnSealDrop func(*types.Block)
+ OnHeaderNew func(*types.Header)
}
// worker is the main object which takes care of submitting new work to consensus engine
@@ -558,6 +559,10 @@ func (w *worker) taskLoop() {
// Reject duplicate sealing work due to resubmitting.
sealHash := w.engine.SealHash(task.block.Header())
if sealHash == prev {
+ log.Warn("Reject duplicate sealing work due to resubmitting.")
+ if w.minerCallbacks.OnSealDrop != nil {
+ w.minerCallbacks.OnSealDrop(task.block)
+ }
continue
}
// Interrupt previous sealing operation
@@ -565,6 +570,9 @@ func (w *worker) taskLoop() {
stopCh, prev = make(chan struct{}), sealHash
if w.skipSealHook != nil && w.skipSealHook(task) {
+ if w.minerCallbacks.OnSealDrop != nil {
+ w.minerCallbacks.OnSealDrop(task.block)
+ }
continue
}
w.pendingMu.Lock()
@@ -636,8 +644,8 @@ func (w *worker) resultLoop() {
}
log.Info("Successfully sealed new block", "number", block.Number(), "sealhash", sealhash, "hash", hash,
"elapsed", common.PrettyDuration(time.Since(task.createdAt)))
- if w.minerCallbacks.OnSeal != nil {
- w.minerCallbacks.OnSeal(block)
+ if w.minerCallbacks.OnSealFinish != nil {
+ w.minerCallbacks.OnSealFinish(block)
}
// Broadcast the block and announce chain insertion event
@@ -883,7 +891,8 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64)
parent := w.chain.CurrentBlock()
if parent.Time() >= uint64(timestamp) {
- timestamp = int64(parent.Time() + 1)
+ //timestamp = int64(parent.Time() + 1)
+ timestamp = int64(parent.Time())
}
// this will ensure we're not going off too far in the future
if now := time.Now().Unix(); timestamp > now+1 {
@@ -925,6 +934,9 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64)
}
}
}
+ if w.minerCallbacks.OnHeaderNew != nil {
+ w.minerCallbacks.OnHeaderNew(header)
+ }
// Could potentially happen if starting to mine in an odd state.
err := w.makeCurrent(parent, header)
if err != nil {
diff --git a/params/protocol_params.go b/params/protocol_params.go
new file mode 100644
index 0000000..c738450
--- /dev/null
+++ b/params/protocol_params.go
@@ -0,0 +1,23 @@
+// Copyright 2015 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library 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.
+//
+// The go-ethereum library 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 the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+package params
+
+//import "math/big"
+
+const (
+ MaximumExtraDataSize uint64 = 64 // Maximum size extra data may be after Genesis.
+)