aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSonic <sonic@dexon.org>2019-05-08 18:28:10 +0800
committerSonic <sonic@dexon.org>2019-05-08 18:28:10 +0800
commit613d4ca4e17de31fce483378192e8e9fbf28be59 (patch)
tree2ecd8d714bb4cb506bcfce277c54066fee881ff9
parent53db7e5a2ae7eb85fa5a2fc412d5746ef6f0f583 (diff)
downloaddexon-613d4ca4e17de31fce483378192e8e9fbf28be59.tar.gz
dexon-613d4ca4e17de31fce483378192e8e9fbf28be59.tar.zst
dexon-613d4ca4e17de31fce483378192e8e9fbf28be59.zip
fixup! light: implement GetGovStateByNumber and InsertDexonHeaderChain (Stub)
-rw-r--r--core/headerchain.go4
-rw-r--r--core/types.go4
-rw-r--r--light/lightchain.go59
-rw-r--r--light/validator.go26
4 files changed, 86 insertions, 7 deletions
diff --git a/core/headerchain.go b/core/headerchain.go
index ef77aa28a..62a2bf805 100644
--- a/core/headerchain.go
+++ b/core/headerchain.go
@@ -465,7 +465,7 @@ func (c *headerVerifierCache) configuration(round uint64) *params.DexconConfig {
func (hc *HeaderChain) ValidateDexonHeaderChain(chain []*types.HeaderWithGovState,
gov dexcon.GovernanceStateFetcher,
- verifierCache *dexCore.TSigVerifierCache, validator Validator) (int, error) {
+ verifierCache *dexCore.TSigVerifierCache, validator HeaderValidator) (int, error) {
// Do a sanity check that the provided chain is actually ordered and linked
for i := 1; i < len(chain); i++ {
if chain[i].Number.Uint64() != chain[i-1].Number.Uint64()+1 || chain[i].ParentHash != chain[i-1].Hash() {
@@ -534,7 +534,7 @@ func (hc *HeaderChain) ValidateDexonHeaderChain(chain []*types.HeaderWithGovStat
func (hc *HeaderChain) VerifyDexonHeader(header *types.Header,
gov dexcon.GovernanceStateFetcher,
- verifierCache *dexCore.TSigVerifierCache, validator Validator) error {
+ verifierCache *dexCore.TSigVerifierCache, validator HeaderValidator) error {
if parent := hc.GetHeader(header.ParentHash, header.Number.Uint64()-1); parent == nil {
return consensus.ErrUnknownAncestor
diff --git a/core/types.go b/core/types.go
index 04a787b1e..8369f2328 100644
--- a/core/types.go
+++ b/core/types.go
@@ -39,6 +39,10 @@ type Validator interface {
ValidateWitnessData(height uint64, data common.Hash) error
}
+type HeaderValidator interface {
+ ValidateWitnessData(height uint64, data common.Hash) error
+}
+
// Processor is an interface for processing blocks using a given initial state.
//
// Process takes the block to be processed and the statedb upon which the
diff --git a/light/lightchain.go b/light/lightchain.go
index a6cdd6f86..232178308 100644
--- a/light/lightchain.go
+++ b/light/lightchain.go
@@ -74,7 +74,8 @@ type LightChain struct {
procInterrupt int32 // interrupt signaler for block processing
wg sync.WaitGroup
- engine consensus.Engine
+ engine consensus.Engine
+ validator core.HeaderValidator
}
// NewLightChain returns a fully initialised light chain using information
@@ -118,6 +119,7 @@ func NewLightChain(odr OdrBackend, config *params.ChainConfig, engine consensus.
log.Error("Chain rewind was successful, resuming normal operation")
}
}
+ bc.validator = &HeaderValidator{chain: bc}
return bc, nil
}
@@ -304,7 +306,18 @@ func (self *LightChain) GetBlockByNumber(ctx context.Context, number uint64) (*t
}
func (self *LightChain) GetGovStateByNumber(number uint64) (*types.GovState, error) {
- return nil, fmt.Errorf("not implemented yet")
+ header := self.GetHeaderByNumber(number)
+ if header == nil {
+ return nil, fmt.Errorf("header not found")
+ }
+
+ govState := rawdb.ReadGovState(self.chainDb, header.Hash())
+ if govState == nil {
+ log.Debug("gov state not found in db")
+ return nil, fmt.Errorf("gov state not found in db")
+ }
+ log.Debug("Read gov state from db success")
+ return govState, nil
}
// Stop stops the blockchain service. If any imports are currently in progress
@@ -401,9 +414,45 @@ func (self *LightChain) InsertHeaderChain(chain []*types.Header, checkFreq int)
return i, err
}
-func (self *LightChain) InsertDexonHeaderChain([]*types.HeaderWithGovState,
- dexcon.GovernanceStateFetcher, *dexCore.TSigVerifierCache) (int, error) {
- return 0, fmt.Errorf("not implemented yet")
+func (self *LightChain) InsertDexonHeaderChain(chain []*types.HeaderWithGovState,
+ gov dexcon.GovernanceStateFetcher, verifierCache *dexCore.TSigVerifierCache) (int, error) {
+ start := time.Now()
+ if i, err := self.hc.ValidateDexonHeaderChain(chain, gov, verifierCache, self.validator); err != nil {
+ return i, err
+ }
+
+ // Make sure only one thread manipulates the chain at once
+ self.chainmu.Lock()
+ defer func() {
+ self.chainmu.Unlock()
+ time.Sleep(time.Millisecond * 10) // ugly hack; do not hog chain lock in case syncing is CPU-limited by validation
+ }()
+
+ self.wg.Add(1)
+ defer self.wg.Done()
+
+ var events []interface{}
+ whFunc := func(header *types.HeaderWithGovState) error {
+ self.mu.Lock()
+ defer self.mu.Unlock()
+
+ status, err := self.hc.WriteDexonHeader(header)
+
+ switch status {
+ case core.CanonStatTy:
+ log.Debug("Inserted new header", "number", header.Number, "hash", header.Hash())
+ events = append(events, core.ChainEvent{Block: types.NewBlockWithHeader(header.Header), Hash: header.Hash()})
+
+ case core.SideStatTy:
+ log.Debug("Inserted forked header", "number", header.Number, "hash", header.Hash())
+ events = append(events, core.ChainSideEvent{Block: types.NewBlockWithHeader(header.Header)})
+ panic("fork found")
+ }
+ return err
+ }
+ i, err := self.hc.InsertDexonHeaderChain(chain, whFunc, start)
+ self.postChainEvents(events)
+ return i, err
}
// CurrentHeader retrieves the current head header of the canonical chain. The
diff --git a/light/validator.go b/light/validator.go
new file mode 100644
index 000000000..7f776bcfb
--- /dev/null
+++ b/light/validator.go
@@ -0,0 +1,26 @@
+package light
+
+import (
+ "github.com/dexon-foundation/dexon/common"
+ "github.com/dexon-foundation/dexon/consensus"
+ "github.com/dexon-foundation/dexon/log"
+)
+
+type HeaderValidator struct {
+ chain *LightChain
+}
+
+func (v *HeaderValidator) ValidateWitnessData(height uint64, blockHash common.Hash) error {
+ b := v.chain.GetHeaderByNumber(height)
+ if b == nil {
+ log.Error("can not find block %v either pending or confirmed block", height)
+ return consensus.ErrWitnessMismatch
+ }
+
+ if b.Hash() != blockHash {
+ log.Error("invalid witness block %s vs %s",
+ b.Hash().String(), blockHash.String())
+ return consensus.ErrWitnessMismatch
+ }
+ return nil
+}