github.com/elastos/Elastos.ELA.SideChain.ETH@v0.2.2/chainbridge-core/blockstore/blockstore.go (about)

     1  // Copyright 2021 ChainSafe Systems
     2  // SPDX-License-Identifier: LGPL-3.0-only
     3  
     4  package blockstore
     5  
     6  import (
     7  	"bytes"
     8  	"errors"
     9  	"fmt"
    10  	"math/big"
    11  
    12  	"github.com/elastos/Elastos.ELA.SideChain.ESC/chainbridge-core/config"
    13  	"github.com/syndtr/goleveldb/leveldb"
    14  )
    15  
    16  type KeyValueReaderWriter interface {
    17  	KeyValueReader
    18  	KeyValueWriter
    19  }
    20  
    21  type KeyValueReader interface {
    22  	GetByKey(key []byte) ([]byte, error)
    23  }
    24  
    25  type KeyValueWriter interface {
    26  	SetByKey(key []byte, value []byte) error
    27  }
    28  
    29  var (
    30  	ErrNotFound = errors.New("key not found")
    31  )
    32  
    33  func StoreBlock(db KeyValueWriter, block *big.Int, chainID uint64) error {
    34  	key := bytes.Buffer{}
    35  	keyS := fmt.Sprintf("chain:%s:block", string(chainID))
    36  	key.WriteString(keyS)
    37  	err := db.SetByKey(key.Bytes(), block.Bytes())
    38  	if err != nil {
    39  		return err
    40  	}
    41  	return nil
    42  }
    43  
    44  func GetLastStoredBlock(db KeyValueReader, chainID uint64) (*big.Int, error) {
    45  	key := bytes.Buffer{}
    46  	keyS := fmt.Sprintf("chain:%s:block", string(chainID))
    47  	key.WriteString(keyS)
    48  	v, err := db.GetByKey(key.Bytes())
    49  	if err != nil {
    50  		if errors.Is(err, leveldb.ErrNotFound) {
    51  			return big.NewInt(0), nil
    52  		}
    53  		return nil, err
    54  	}
    55  	block := big.NewInt(0).SetBytes(v)
    56  	return block, nil
    57  }
    58  
    59  // SetupBlockstore queries the blockstore for the latest known block. If the latest block is
    60  // greater than config.StartBlock, then config.StartBlock is replaced with the latest known block.
    61  func SetupBlockstore(generalConfig *config.GeneralChainConfig, kvdb KeyValueReaderWriter, startBlock *big.Int) (*big.Int, error) {
    62  	latestBlock, err := GetLastStoredBlock(kvdb, generalConfig.Id)
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  
    67  	if !generalConfig.FreshStart {
    68  		if latestBlock.Cmp(startBlock) == 1 {
    69  			return latestBlock, nil
    70  		} else {
    71  			return startBlock, nil
    72  		}
    73  	}
    74  	return startBlock, nil
    75  }