Skip to content

Commit

Permalink
Release 3.0.0 (#805)
Browse files Browse the repository at this point in the history
* knode/genesis: modified testnet base deposit to 30000 (#770)

* Fix panic while chain sync (#788)

* more context for some errors

* check are blocks equal at the reOrg stage

* fmt

* extrect IsEqual block method

* extract IsParent method in block type

* fixed warn on already latest version

* fmted

* Revert "knode/genesis: modified testnet base deposit to 30000 (#770)" (#790)

This reverts commit 0ce9045.

* knode/validator: included timeouts for tx confirmations (#795)

* Log duplicate vote type and author (#797)

* duplicate vote logging

* fmt

* warn log level for nil-voting

* prevent log spamming

* discovery topic include chain and network IDs

* fmt
  • Loading branch information
acroca authored and yourheropaul committed Oct 4, 2018
1 parent 0a09529 commit 1573b9b
Show file tree
Hide file tree
Showing 20 changed files with 154 additions and 59 deletions.
3 changes: 1 addition & 2 deletions client/cmd/kcoin/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"github.com/kowala-tech/kcoin/client/node"
"gopkg.in/urfave/cli.v1"
"github.com/kowala-tech/kcoin/client/version"
"github.com/blang/semver"
"github.com/kowala-tech/kcoin/client/params"
)

Expand Down Expand Up @@ -359,7 +358,7 @@ func mustBeLatestMajorVersion(ctx *cli.Context) {
return
}

current, err := semver.Make(params.Version)
current, err := version.MakeSemver(params.Version)
if err != nil {
log.Error("Error parsing current version, exiting checker", "err", err)
return
Expand Down
11 changes: 9 additions & 2 deletions client/common/tx/confirmation.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,22 @@ type Backend interface {
TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error)
}

// WaitMinedWithTimeout waits for tx to be mined on the blockchain within a given period of time.
func WaitMinedWithTimeout(backend Backend, txHash common.Hash, duration time.Duration) (*types.Receipt, error) {
ctx, cancel := context.WithTimeout(context.Background(), duration)
defer cancel()
return WaitMined(ctx, backend, txHash)
}

// WaitMined waits for tx to be mined on the blockchain.
// It stops waiting when the context is canceled.
func WaitMined(ctx context.Context, b Backend, txHash common.Hash) (*types.Receipt, error) {
func WaitMined(ctx context.Context, backend Backend, txHash common.Hash) (*types.Receipt, error) {
queryTicker := time.NewTicker(time.Second)
defer queryTicker.Stop()

logger := log.New("hash", txHash)
for {
receipt, err := b.TransactionReceipt(ctx, txHash)
receipt, err := backend.TransactionReceipt(ctx, txHash)
if receipt != nil {
return receipt, nil
}
Expand Down
2 changes: 2 additions & 0 deletions client/contracts/bindings/oracle/oracle.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/kowala-tech/kcoin/client/accounts/abi/bind"
"github.com/kowala-tech/kcoin/client/common/kns"
"github.com/kowala-tech/kcoin/client/contracts/bindings"
"github.com/kowala-tech/kcoin/client/log"
"github.com/kowala-tech/kcoin/client/params"
)

Expand All @@ -30,6 +31,7 @@ func Bind(contractBackend bind.ContractBackend, chainID *big.Int) (bindings.Bind
contractBackend,
)
if err != nil {
log.Error("can't find Oracle for given Network", "chainID", chainID.String())
return nil, bindings.ErrNoAddress
}

Expand Down
5 changes: 3 additions & 2 deletions client/contracts/bindings/stability/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ package stability
import (
"math/big"

"github.com/kowala-tech/kcoin/client/common/kns"

"github.com/kowala-tech/kcoin/client/accounts/abi/bind"
"github.com/kowala-tech/kcoin/client/common/kns"
"github.com/kowala-tech/kcoin/client/contracts/bindings"
"github.com/kowala-tech/kcoin/client/log"
"github.com/kowala-tech/kcoin/client/params"
)

Expand All @@ -29,6 +29,7 @@ func Bind(contractBackend bind.ContractBackend, chainID *big.Int) (bindings.Bind
contractBackend,
)
if err != nil {
log.Error("can't find Stability contract for given Network", "chainID", chainID.String())
return nil, bindings.ErrNoAddress
}

Expand Down
5 changes: 3 additions & 2 deletions client/contracts/bindings/sysvars/vars.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ package sysvars
import (
"math/big"

"github.com/kowala-tech/kcoin/client/common/kns"

"github.com/kowala-tech/kcoin/client/accounts/abi/bind"
"github.com/kowala-tech/kcoin/client/common/kns"
"github.com/kowala-tech/kcoin/client/contracts/bindings"
"github.com/kowala-tech/kcoin/client/log"
"github.com/kowala-tech/kcoin/client/params"
)

Expand All @@ -29,6 +29,7 @@ func Bind(contractBackend bind.ContractBackend, chainID *big.Int) (bindings.Bind
contractBackend,
)
if err != nil {
log.Error("can't find SystemVar for given Network", "chainID", chainID.String())
return nil, bindings.ErrNoAddress
}

Expand Down
26 changes: 16 additions & 10 deletions client/core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"sync/atomic"
"time"

"github.com/davecgh/go-spew/spew"
"github.com/hashicorp/golang-lru"
"github.com/kowala-tech/kcoin/client/common"
"github.com/kowala-tech/kcoin/client/common/mclock"
Expand All @@ -28,7 +29,6 @@ import (
"github.com/kowala-tech/kcoin/client/rlp"
"github.com/kowala-tech/kcoin/client/trie"
"gopkg.in/karalabe/cookiejar.v2/collections/prque"
"github.com/davecgh/go-spew/spew"
)

var (
Expand Down Expand Up @@ -922,10 +922,7 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types.

func (bc *BlockChain) doReorg(block *types.Block, currentBlock *types.Block, batch kcoindb.Batch, state *state.StateDB) (WriteStatus, error) {
// Reorganise the chain if the parent is not the head block
if IsHead(block, currentBlock) {
log.Warn(fmt.Sprintf("a blockchain reorganization needed: block parent hash %v, current block hash %v",
block.ParentHash().String(), currentBlock.Hash().String()))

if !currentBlock.IsParent(block) {
if err := bc.reorg(currentBlock, block); err != nil {
return NonStatTy, err
}
Expand All @@ -940,10 +937,6 @@ func writePositionalMetadata(batch kcoindb.Batch, block *types.Block, state *sta
rawdb.WritePreimages(batch, block.NumberU64(), state.Preimages())
}

func IsHead(block *types.Block, currentBlock *types.Block) bool {
return block.ParentHash() != currentBlock.Hash()
}

func (bc *BlockChain) isReorgState(block *types.Block, currentBlock *types.Block) bool {
reorg := block.Number().Cmp(currentBlock.Number()) > 0
if !reorg && block.Number().Cmp(currentBlock.Number()) == 0 {
Expand Down Expand Up @@ -1196,6 +1189,14 @@ func countTransactions(chain []*types.Block) (c int) {
// to be part of the new canonical chain and accumulates potential missing transactions and post an
// event about them
func (bc *BlockChain) reorg(oldBlock, newBlock *types.Block) error {
if oldBlock.IsSame(newBlock) {
// don't need a reorg if got the same block as old and new ones
return nil
}
log.Warn(fmt.Sprintf("a blockchain reorganization needed: block parent hash %v(%d), current block hash %v(%d)",
newBlock.ParentHash().String(), newBlock.Number().Int64()-1,
oldBlock.Hash().String(), oldBlock.Number().Int64()))

var (
newChain types.Blocks
oldChain types.Blocks
Expand Down Expand Up @@ -1272,7 +1273,12 @@ func (bc *BlockChain) reorg(oldBlock, newBlock *types.Block) error {
logFn("Chain split detected", "number", commonBlock.Number(), "hash", commonBlock.Hash(),
"drop", len(oldChain), "dropfrom", oldChain[0].Hash(), "add", len(newChain), "addfrom", newChain[0].Hash())
} else {
log.Error("Impossible reorg, please file an issue", "oldnum", oldBlock.Number(), "oldhash", oldBlock.Hash(), "len(oldChain)", len(oldChain), "newnum", newBlock.Number(), "newhash", newBlock.Hash(), "len(newChain)", len(newChain))
log.Error("Impossible reorg, please file an issue",
"oldnum", oldBlock.Number(),
"oldhash", oldBlock.Hash(),
"len(oldChain)", len(oldChain),
"newnum", newBlock.Number(),
"newhash", newBlock.Hash(), "len(newChain)", len(newChain))
}
// Insert the new chain, taking care of the proper incremental order
var addedTxs types.Transactions
Expand Down
8 changes: 7 additions & 1 deletion client/core/headerchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,18 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er
rawdb.DeleteCanonicalHash(batch, i)
}
batch.Write()

// Overwrite any stale canonical number assignments
var (
headHash = header.ParentHash
headNumber = header.Number.Uint64() - 1
headHeader = hc.GetHeader(headHash, headNumber)
)
if headHeader == nil {
log.Error("error processing block head", "hash", headHash, "number", headNumber)
log.Error("error processing block head. additional info", "headerByHash", hc.GetHeaderByHash(headHash))
log.Error("error processing block head. additional info", "headerByNumber", hc.GetHeaderByNumber(headNumber))
}
for rawdb.ReadCanonicalHash(hc.chainDb, headNumber) != headHash {
rawdb.WriteCanonicalHash(hc.chainDb, headHash, headNumber)

Expand Down Expand Up @@ -175,7 +181,7 @@ func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header, checkFreq int)
// 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() {
// Chain broke ancestry, log a messge (programming error) and skip insertion
// Chain broke ancestry, log a message (programming error) and skip insertion
log.Error("Non contiguous header insert", "number", chain[i].Number, "hash", chain[i].Hash(),
"parent", chain[i].ParentHash, "prevnumber", chain[i-1].Number, "prevhash", chain[i-1].Hash())

Expand Down
11 changes: 11 additions & 0 deletions client/core/types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package types

import (
"bytes"
"io"
"math/big"
"sort"
Expand Down Expand Up @@ -352,6 +353,16 @@ func (b *Block) AsFragments(size int) (*BlockFragments, error) {
return NewDataSetFromData(rawBlock, size), nil
}

// IsSame returns true if blocks have same hashes and block numbers
func (b *Block) IsSame(to *Block) bool {
return b.Number().Cmp(to.Number()) == 0 && bytes.Equal(b.Hash().Bytes(), to.Hash().Bytes())
}

// IsParent returns true if child block have parent hashes in ParentHash and block number greater by 1
func (b *Block) IsParent(childBlock *Block) bool {
return b.Number().Int64()+1 == childBlock.Number().Int64() && bytes.Equal(b.Hash().Bytes(), childBlock.ParentHash().Bytes())
}

type Blocks []*Block

type BlockBy func(b1, b2 *Block) bool
Expand Down
19 changes: 16 additions & 3 deletions client/core/types/vote.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package types

import (
"bytes"
"errors"
"fmt"
"io"
"math/big"
Expand Down Expand Up @@ -256,16 +257,28 @@ func (v *VotesSet) Add(vote *Vote) {
}
}

func (v *VotesSet) Contains(h common.Hash) bool {
var (
errNonNilDuplicate = errors.New("duplicate NON-NIL vote")
errNilDuplicate = errors.New("duplicate NIL vote")
)

func (v *VotesSet) Contains(h common.Hash) error {
v.l.RLock()
defer v.l.RUnlock()

_, res := v.m[h]
if res {
return errNonNilDuplicate
}

if !res {
_, res = v.nilVotes[h]
if res {
return errNilDuplicate
}
}

v.l.RUnlock()
return res
return nil
}

func (v *VotesSet) Len() int {
Expand Down
21 changes: 11 additions & 10 deletions client/core/voting_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import (
"github.com/kowala-tech/kcoin/client/log"
)

var ErrDuplicateVote = errors.New("duplicate vote")

type VotingTable interface {
Add(vote types.AddressVote) error
Leader() common.Hash
Expand Down Expand Up @@ -42,14 +40,11 @@ func (table *votingTable) Add(voteAddressed types.AddressVote) error {
if !table.isVoter(voteAddressed.Address()) {
return fmt.Errorf("voter address not found in voting table: 0x%x", voteAddressed.Address().Hash())
}

vote := voteAddressed.Vote()
if table.isDuplicate(vote) {
log.Error(fmt.Sprintf("a duplicate vote in voting table %v; blockHash %v; voteHash %v. Error: %s",
table.voteType, vote.BlockHash(), vote.Hash(), vote.String()))
return ErrDuplicateVote
if err := table.isDuplicate(voteAddressed); err != nil {
return err
}

vote := voteAddressed.Vote()
table.votes.Add(vote)

if table.hasQuorum() {
Expand All @@ -64,8 +59,14 @@ func (table *votingTable) Leader() common.Hash {
return table.votes.Leader()
}

func (table *votingTable) isDuplicate(vote *types.Vote) bool {
return table.votes.Contains(vote.Hash())
func (table *votingTable) isDuplicate(voteAddressed types.AddressVote) error {
vote := voteAddressed.Vote()
err := table.votes.Contains(vote.Hash())
if err != nil {
log.Error(fmt.Sprintf("a duplicate vote in voting table %v; blockHash %v; voteHash %v; from validator %v. Error: %s",
table.voteType, vote.BlockHash(), vote.Hash(), voteAddressed.Address(), vote.String()))
}
return err
}

func (table *votingTable) isVoter(address common.Address) bool {
Expand Down
5 changes: 4 additions & 1 deletion client/knode/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -467,9 +467,12 @@ func (s *Kowala) Start(srvr *p2p.Server) error {
}
}


//fixme: should be removed after develop light client
if srvr.DiscoveryV5 {
protocolTopic := discv5.DiscoveryTopic(s.blockchain.Genesis().Hash(), protocol.ProtocolName, protocol.Kcoin1)
chainID := s.chainConfig.ChainID.Int64()
networkID := s.networkID
protocolTopic := discv5.DiscoveryTopic(s.blockchain.Genesis().Hash(), protocol.ProtocolName, protocol.Kcoin1, networkID, chainID)

go func() {
srvr.DiscV5.RegisterTopic(protocolTopic, s.shutdownChan)
Expand Down
3 changes: 1 addition & 2 deletions client/knode/validator/states.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package validator

import (
"bytes"
"context"
"fmt"
"math/big"
"sync/atomic"
Expand Down Expand Up @@ -58,7 +57,7 @@ func (val *validator) notLoggedInState() stateFn {
}
log.Info("Waiting confirmation to participate in the consensus")

receipt, err := tx.WaitMined(context.TODO(), val.backend, txHash)
receipt, err := tx.WaitMinedWithTimeout(val.backend, txHash, txConfirmationTimeout)
if err != nil {
log.Crit("Failed to verify the voter registration", "err", err)
}
Expand Down
14 changes: 9 additions & 5 deletions client/knode/validator/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ var (
ErrIsRunning = errors.New("validator is running, cannot change its parameters")
)

var (
txConfirmationTimeout = 10 * time.Second
)

// Backend wraps all methods required for mining.
type Backend interface {
BlockChain() *core.BlockChain
Expand Down Expand Up @@ -416,7 +420,7 @@ func (val *validator) leave() {
if err != nil {
log.Error("failed to leave the election", "err", err)
}
receipt, err := tx.WaitMined(context.TODO(), val.backend, txHash)
receipt, err := tx.WaitMinedWithTimeout(val.backend, txHash, txConfirmationTimeout)
if err != nil {
log.Error("Failed to verify the voter deregistration", "err", err)
}
Expand Down Expand Up @@ -531,7 +535,7 @@ func (val *validator) preVote() {
log.Debug("Locked Block is not nil, voting for the locked block")
vote = val.lockedBlock.Hash()
case val.block == nil:
log.Debug("Proposal's block is nil, voting nil")
log.Warn("Proposal's block is nil, voting nil")
vote = common.Hash{}
default:
log.Debug("Voting for the proposal's block")
Expand All @@ -556,7 +560,7 @@ func (val *validator) preCommit() {
// no majority
// majority pre-voted nil
case currentLeader == common.Hash{}:
log.Debug("Majority of validators pre-voted nil")
log.Warn("Majority of validators pre-voted nil")
// unlock locked block
if val.lockedBlock != nil {
val.lockedRound = 0
Expand All @@ -579,7 +583,7 @@ func (val *validator) preCommit() {
default:
// fetch block, unlock, precommit
// unlock locked block
log.Debug("preCommit default case")
log.Warn("preCommit default case")
val.lockedRound = 0
val.lockedBlock = nil
val.block = nil
Expand Down Expand Up @@ -734,7 +738,7 @@ func (val *validator) RedeemDeposits() error {
if err != nil {
return err
}
receipt, err := tx.WaitMined(context.TODO(), val.backend, txHash)
receipt, err := tx.WaitMinedWithTimeout(val.backend, txHash, txConfirmationTimeout)
if err != nil {
return err
}
Expand Down
Loading

0 comments on commit 1573b9b

Please sign in to comment.