diff options
author | Sonic <sonic@dexon.org> | 2019-05-08 18:28:10 +0800 |
---|---|---|
committer | Sonic <sonic@dexon.org> | 2019-05-08 18:28:10 +0800 |
commit | 613d4ca4e17de31fce483378192e8e9fbf28be59 (patch) | |
tree | 2ecd8d714bb4cb506bcfce277c54066fee881ff9 | |
parent | 53db7e5a2ae7eb85fa5a2fc412d5746ef6f0f583 (diff) | |
download | dexon-613d4ca4e17de31fce483378192e8e9fbf28be59.tar.gz dexon-613d4ca4e17de31fce483378192e8e9fbf28be59.tar.zst dexon-613d4ca4e17de31fce483378192e8e9fbf28be59.zip |
fixup! light: implement GetGovStateByNumber and InsertDexonHeaderChain (Stub)
-rw-r--r-- | core/headerchain.go | 4 | ||||
-rw-r--r-- | core/types.go | 4 | ||||
-rw-r--r-- | light/lightchain.go | 59 | ||||
-rw-r--r-- | light/validator.go | 26 |
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 +} |