Skip to content

Commit

Permalink
Merge branch 'beta' into feature/xeno_transaction
Browse files Browse the repository at this point in the history
  • Loading branch information
leventeliu authored Jan 17, 2019
2 parents 5393e18 + 6026fab commit 495f14e
Show file tree
Hide file tree
Showing 12 changed files with 253 additions and 154 deletions.
2 changes: 1 addition & 1 deletion blockproducer/blocknode.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func newBlockNode(h uint32, b *types.BPBlock, p *blockNode) *blockNode {
}(),
height: h,

hash: b.SignedHeader.BlockHash,
hash: b.SignedHeader.DataHash,
block: b,
}
}
Expand Down
41 changes: 28 additions & 13 deletions blockproducer/blocknode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"testing"

"github.com/CovenantSQL/CovenantSQL/crypto/hash"
"github.com/CovenantSQL/CovenantSQL/crypto/verifier"
"github.com/CovenantSQL/CovenantSQL/types"
. "github.com/smartystreets/goconvey/convey"
)
Expand All @@ -29,39 +30,49 @@ func TestBlockNode(t *testing.T) {
var (
b0 = &types.BPBlock{
SignedHeader: types.BPSignedHeader{
BlockHash: hash.Hash{0x1},
DefaultHashSignVerifierImpl: verifier.DefaultHashSignVerifierImpl{
DataHash: hash.Hash{0x1},
},
},
}
b1 = &types.BPBlock{
SignedHeader: types.BPSignedHeader{
BPHeader: types.BPHeader{
ParentHash: b0.SignedHeader.BlockHash,
ParentHash: b0.SignedHeader.DataHash,
},
DefaultHashSignVerifierImpl: verifier.DefaultHashSignVerifierImpl{
DataHash: hash.Hash{0x2},
},
BlockHash: hash.Hash{0x2},
},
}
b2 = &types.BPBlock{
SignedHeader: types.BPSignedHeader{
BPHeader: types.BPHeader{
ParentHash: b1.SignedHeader.BlockHash,
ParentHash: b1.SignedHeader.DataHash,
},
DefaultHashSignVerifierImpl: verifier.DefaultHashSignVerifierImpl{
DataHash: hash.Hash{0x3},
},
BlockHash: hash.Hash{0x3},
},
}
b3 = &types.BPBlock{
SignedHeader: types.BPSignedHeader{
BPHeader: types.BPHeader{
ParentHash: b2.SignedHeader.BlockHash,
ParentHash: b2.SignedHeader.DataHash,
},
DefaultHashSignVerifierImpl: verifier.DefaultHashSignVerifierImpl{
DataHash: hash.Hash{0x4},
},
BlockHash: hash.Hash{0x4},
},
}
b4 = &types.BPBlock{
SignedHeader: types.BPSignedHeader{
BPHeader: types.BPHeader{
ParentHash: b3.SignedHeader.BlockHash,
ParentHash: b3.SignedHeader.DataHash,
},
DefaultHashSignVerifierImpl: verifier.DefaultHashSignVerifierImpl{
DataHash: hash.Hash{0x5},
},
BlockHash: hash.Hash{0x5},
},
}
n0 = newBlockNode(0, b0, nil)
Expand All @@ -73,17 +84,21 @@ func TestBlockNode(t *testing.T) {
b3p = &types.BPBlock{
SignedHeader: types.BPSignedHeader{
BPHeader: types.BPHeader{
ParentHash: b2.SignedHeader.BlockHash,
ParentHash: b2.SignedHeader.DataHash,
},
DefaultHashSignVerifierImpl: verifier.DefaultHashSignVerifierImpl{
DataHash: hash.Hash{0x6},
},
BlockHash: hash.Hash{0x6},
},
}
b4p = &types.BPBlock{
SignedHeader: types.BPSignedHeader{
BPHeader: types.BPHeader{
ParentHash: b3p.SignedHeader.BlockHash,
ParentHash: b3p.SignedHeader.DataHash,
},
DefaultHashSignVerifierImpl: verifier.DefaultHashSignVerifierImpl{
DataHash: hash.Hash{0x7},
},
BlockHash: hash.Hash{0x7},
},
}
n3p = newBlockNode(3, b3p, n2)
Expand Down
47 changes: 23 additions & 24 deletions blockproducer/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import (
"github.com/CovenantSQL/CovenantSQL/crypto/asymmetric"
"github.com/CovenantSQL/CovenantSQL/crypto/hash"
"github.com/CovenantSQL/CovenantSQL/crypto/kms"
"github.com/CovenantSQL/CovenantSQL/merkle"
"github.com/CovenantSQL/CovenantSQL/proto"
"github.com/CovenantSQL/CovenantSQL/route"
"github.com/CovenantSQL/CovenantSQL/rpc"
Expand Down Expand Up @@ -113,15 +112,29 @@ func NewChainWithContext(ctx context.Context, cfg *Config) (c *Chain, err error)
bus = chainbus.New()
)

if fi, err := os.Stat(cfg.DataFile); err == nil && fi.Mode().IsRegular() {
existed = true
// Verify genesis block in config
if cfg.Genesis == nil {
err = ErrNilGenesis
return
}
if ierr = cfg.Genesis.VerifyHash(); ierr != nil {
err = errors.Wrap(ierr, "failed to verify genesis block hash")
return
}

// Open storage
if fi, err := os.Stat(cfg.DataFile); err == nil && fi.Mode().IsRegular() {
existed = true
}
if st, ierr = openStorage(fmt.Sprintf("file:%s", cfg.DataFile)); ierr != nil {
err = errors.Wrap(ierr, "failed to open storage")
return
}
defer func() {
if err != nil {
st.Close()
}
}()

// Create initial state from genesis block and store
if !existed {
Expand All @@ -134,7 +147,7 @@ func NewChainWithContext(ctx context.Context, cfg *Config) (c *Chain, err error)
}
var sps = init.compileChanges(nil)
sps = append(sps, addBlock(0, cfg.Genesis))
sps = append(sps, updateIrreversible(cfg.Genesis.SignedHeader.BlockHash))
sps = append(sps, updateIrreversible(cfg.Genesis.SignedHeader.DataHash))
if ierr = store(st, sps, nil); ierr != nil {
err = errors.Wrap(ierr, "failed to initialize storage")
return
Expand All @@ -146,6 +159,11 @@ func NewChainWithContext(ctx context.Context, cfg *Config) (c *Chain, err error)
err = errors.Wrap(ierr, "failed to load data from storage")
return
}
if persistedGenesis := irre.ancestorByCount(0); persistedGenesis == nil ||
!persistedGenesis.hash.IsEqual(cfg.Genesis.BlockHash()) {
err = ErrGenesisHashNotMatch
return
}
for _, v := range heads {
log.WithFields(log.Fields{
"irre_hash": irre.hash.Short(4),
Expand Down Expand Up @@ -279,28 +297,9 @@ func (c *Chain) Stop() (err error) {
return
}

// checkBlock has following steps: 1. check parent block 2. checkTx 2. merkle tree 3. Hash 4. Signature.
func (c *Chain) checkBlock(b *types.BPBlock) (err error) {
rootHash := merkle.NewMerkle(b.GetTxHashes()).GetRoot()
if !b.SignedHeader.MerkleRoot.IsEqual(rootHash) {
return ErrInvalidMerkleTreeRoot
}

enc, err := b.SignedHeader.BPHeader.MarshalHash()
if err != nil {
return err
}
h := hash.THashH(enc)
if !b.BlockHash().IsEqual(&h) {
return ErrInvalidHash
}

return nil
}

func (c *Chain) pushBlock(b *types.BPBlock) (err error) {
var ierr error
if ierr = c.checkBlock(b); ierr != nil {
if ierr = b.Verify(); ierr != nil {
err = errors.Wrap(ierr, "failed to check block")
return
}
Expand Down
46 changes: 44 additions & 2 deletions blockproducer/chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/CovenantSQL/CovenantSQL/proto"
"github.com/CovenantSQL/CovenantSQL/rpc"
"github.com/CovenantSQL/CovenantSQL/types"
"github.com/pkg/errors"
. "github.com/smartystreets/goconvey/convey"
)

Expand Down Expand Up @@ -121,7 +122,7 @@ func TestChain(t *testing.T) {
}),
},
}
err = genesis.PackAndSignBlock(testingPrivateKey)
err = genesis.SetHash()
So(err, ShouldBeNil)
begin = genesis.Timestamp()

Expand All @@ -147,7 +148,7 @@ func TestChain(t *testing.T) {

Convey("A new chain running before genesis time should be waiting for genesis", func() {
config.Genesis.SignedHeader.Timestamp = time.Now().Add(24 * time.Hour)
err = genesis.PackAndSignBlock(testingPrivateKey)
err = genesis.SetHash()
So(err, ShouldBeNil)
chain, err = NewChain(config)
So(err, ShouldBeNil)
Expand Down Expand Up @@ -312,6 +313,47 @@ func TestChain(t *testing.T) {
chain.stat()
})

Convey("The chain should report error if genesis in config is cleared", func() {
err = chain.Stop()
So(err, ShouldBeNil)
config.Genesis = nil
chain, err = NewChain(config)
So(err, ShouldEqual, ErrNilGenesis)
So(chain, ShouldBeNil)
})

Convey("The chain should report error if config is changed", func() {
err = chain.Stop()
So(err, ShouldBeNil)
config.Genesis.Transactions = append(
config.Genesis.Transactions,
types.NewBaseAccount(&types.Account{
Address: addr2,
TokenBalance: [5]uint64{1000, 1000, 1000, 1000, 1000},
}),
)
chain, err = NewChain(config)
So(errors.Cause(err), ShouldEqual, types.ErrMerkleRootVerification)
So(chain, ShouldBeNil)
})

Convey("The chain should report error if config is changed and rehashed", func() {
err = chain.Stop()
So(err, ShouldBeNil)
config.Genesis.Transactions = append(
config.Genesis.Transactions,
types.NewBaseAccount(&types.Account{
Address: addr2,
TokenBalance: [5]uint64{1000, 1000, 1000, 1000, 1000},
}),
)
err = config.Genesis.SetHash()
So(err, ShouldBeNil)
chain, err = NewChain(config)
So(err, ShouldEqual, ErrGenesisHashNotMatch)
So(chain, ShouldBeNil)
})

Convey("The chain APIs should return expected results", func() {
var (
bl *types.BPBlock
Expand Down
7 changes: 5 additions & 2 deletions blockproducer/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ var (
ErrInvalidHash = errors.New("Hash is invalid")
// ErrExistedTx defines existed tx error.
ErrExistedTx = errors.New("Tx existed")
// ErrInvalidMerkleTreeRoot defines invalid merkle tree root error.
ErrInvalidMerkleTreeRoot = errors.New("Block merkle tree root does not match the tx hashes")
// ErrParentNotMatch defines invalid parent hash.
ErrParentNotMatch = errors.New("Block's parent hash cannot match best block")
// ErrTooManyTransactionsInBlock defines error of too many transactions in a block.
Expand Down Expand Up @@ -70,8 +68,13 @@ var (
ErrMinerUserNotMatch = errors.New("miner and user do not match")
// ErrInsufficientAdvancePayment indicates that the advance payment is insufficient.
ErrInsufficientAdvancePayment = errors.New("insufficient advance payment")
// ErrNilGenesis indicates that the genesis block is nil in config.
ErrNilGenesis = errors.New("nil genesis block")
// ErrMultipleGenesis indicates that there're multiple genesis blocks while loading.
ErrMultipleGenesis = errors.New("multiple genesis blocks")
// ErrGenesisHashNotMatch indicates that the genesis block hash in config doesn't match
// the persisted one.
ErrGenesisHashNotMatch = errors.New("persisted genesis block hash not match")
// ErrInvalidGasPrice indicates that the gas price is invalid.
ErrInvalidGasPrice = errors.New("gas price is invalid")
// ErrInvalidMinerCount indicates that the miner node count is invalid.
Expand Down
23 changes: 13 additions & 10 deletions cmd/cqld/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ const (
func runNode(nodeID proto.NodeID, listenAddr string) (err error) {
rootPath := conf.GConf.WorkingRoot

genesis := loadGenesis()
genesis, err := loadGenesis()
if err != nil {
return
}

var masterKey []byte
if !conf.GConf.IsTestMode {
Expand Down Expand Up @@ -226,20 +229,16 @@ func initKayakTwoPC(rootDir string, node *proto.Node, peers *proto.Peers, h kt.H
return
}

func loadGenesis() *types.BPBlock {
func loadGenesis() (genesis *types.BPBlock, err error) {
genesisInfo := conf.GConf.BP.BPGenesis
log.WithField("config", genesisInfo).Info("load genesis config")

genesis := &types.BPBlock{
genesis = &types.BPBlock{
SignedHeader: types.BPSignedHeader{
BPHeader: types.BPHeader{
Version: genesisInfo.Version,
Producer: proto.AccountAddress(genesisInfo.Producer),
MerkleRoot: genesisInfo.MerkleRoot,
ParentHash: genesisInfo.ParentHash,
Timestamp: genesisInfo.Timestamp,
Version: genesisInfo.Version,
Timestamp: genesisInfo.Timestamp,
},
BlockHash: genesisInfo.BlockHash,
},
}

Expand All @@ -256,5 +255,9 @@ func loadGenesis() *types.BPBlock {
}))
}

return genesis
// Rewrite genesis merkle and block hash
if err = genesis.SetHash(); err != nil {
return
}
return
}
8 changes: 0 additions & 8 deletions conf/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,8 @@ type BaseAccountInfo struct {
type BPGenesisInfo struct {
// Version defines the block version
Version int32 `yaml:"Version"`
// Producer defines the block producer
Producer hash.Hash `yaml:"Producer"`
// MerkleRoot defines the transaction merkle tree's root
MerkleRoot hash.Hash `yaml:"MerkleRoot"`
// ParentHash defines the parent block's hash
ParentHash hash.Hash `yaml:"ParentHash"`
// Timestamp defines the initial time of chain
Timestamp time.Time `yaml:"Timestamp"`
// BlockHash defines the block hash of genesis block
BlockHash hash.Hash `yaml:"BlockHash"`
// BaseAccounts defines the base accounts for testnet
BaseAccounts []BaseAccountInfo `yaml:"BaseAccounts"`
}
Expand Down
8 changes: 2 additions & 6 deletions conf/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,8 @@ func TestConf(t *testing.T) {
},
ChainFileName: "",
BPGenesis: BPGenesisInfo{
Version: 1,
Producer: h,
MerkleRoot: h,
ParentHash: h,
Timestamp: time.Now().UTC(),
BlockHash: h,
Version: 1,
Timestamp: time.Now().UTC(),
},
}
Convey("LoadConfig", t, func() {
Expand Down
Loading

0 comments on commit 495f14e

Please sign in to comment.