Skip to content

Commit c14d0cf

Browse files
Merge pull request #166 from canopy-network/issue-#151
issue-#151
2 parents afc1b6c + 9e6815f commit c14d0cf

15 files changed

Lines changed: 400 additions & 102 deletions

File tree

bft/bft.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ import (
1313

1414
// BFT is a structure that holds data for a Hotstuff BFT instance
1515
type BFT struct {
16-
*lib.View // the current period during which the BFT is occurring (CreatedHeight/Round/Phase)
16+
*lib.View // the current period during which the BFT is occurring (Height/Round/Phase)
1717
Votes VotesForHeight // 'votes' received from Replica (non-leader) Validators
1818
Proposals ProposalsForHeight // 'proposals' received from the Leader Validator(s)
1919
ProposerKey []byte // the public key of the proposer
2020
ValidatorSet ValSet // the current set of Validators
21-
HighQC *QC // the highest PRECOMMIT quorum certificate the node is aware of for this CreatedHeight
21+
HighQC *QC // the highest PRECOMMIT quorum certificate the node is aware of for this Height
2222
Block []byte // the current Block being voted on (the foundational unit of the blockchain)
2323
BlockHash []byte // the current hash of the block being voted on
2424
Results *lib.CertificateResult // the current Result being voted on (reward and slash recipients)
@@ -101,6 +101,8 @@ func (b *BFT) Start() {
101101
func() {
102102
b.Controller.Lock()
103103
defer b.Controller.Unlock()
104+
// Update BFT metrics
105+
defer b.Metrics.UpdateBFTMetrics(b.Height, b.RootHeight, b.Round, b.Phase, time.Now())
104106
// handle the phase
105107
b.HandlePhase()
106108
}()
@@ -240,7 +242,7 @@ func (b *BFT) StartElectionVotePhase() {
240242
Header: b.View.Copy(),
241243
ProposerKey: b.ProposerKey, // using voting power, authorizes Candidate to act as the 'Leader'
242244
},
243-
HighQc: b.HighQC, // forward highest known 'Lock' for this CreatedHeight, so the new Proposer may satisfy SAFE-NODE-PREDICATE
245+
HighQc: b.HighQC, // forward highest known 'Lock' for this Height, so the new Proposer may satisfy SAFE-NODE-PREDICATE
244246
LastDoubleSignEvidence: b.ByzantineEvidence.DSE.Evidence, // forward any evidence of DoubleSigning
245247
Vdf: b.HighVDF, // forward local VDF to the candidate
246248
})
@@ -249,7 +251,7 @@ func (b *BFT) StartElectionVotePhase() {
249251
// StartProposePhase() begins the ProposePhase after the ELECTION-VOTE phase timeout
250252
// PROPOSE PHASE:
251253
// - Leader reviews the collected vote messages from Replicas
252-
// - Determines the highest 'lock' (HighQC) if one exists for this CreatedHeight
254+
// - Determines the highest 'lock' (HighQC) if one exists for this Height
253255
// - Combines any ByzantineEvidence sent from Replicas into their own
254256
// - Aggregates the signatures from the Replicas to form a +2/3 threshold multi-signature
255257
//
@@ -292,7 +294,7 @@ func (b *BFT) StartProposePhase() {
292294
// StartProposeVotePhase() begins the ProposeVote after the PROPOSE phase timeout
293295
// PROPOSE-VOTE PHASE:
294296
// - Replica reviews the message from the Leader by validating the justification (+2/3 multi-sig) proving that they are in-fact the leader
295-
// - If the Replica is currently Locked on a previous Proposal for this CreatedHeight, the new Proposal must pass the SAFE-NODE-PREDICATE
297+
// - If the Replica is currently Locked on a previous Proposal for this Height, the new Proposal must pass the SAFE-NODE-PREDICATE
296298
// - Replica Validates the proposal using the byzantine evidence and the specific plugin
297299
// - Replicas send a signed (aggregable) PROPOSE vote to the Leader
298300
func (b *BFT) StartProposeVotePhase() {
@@ -592,8 +594,6 @@ func (b *BFT) NewHeight(keepLocks ...bool) {
592594
b.Height = b.Controller.ChainHeight()
593595
// update canopy height
594596
b.RootHeight = b.Controller.RootChainHeight()
595-
// Update BFT metrics
596-
b.Metrics.UpdateBFTMetrics(b.Height, b.RootHeight)
597597
// update the validator set
598598
b.ValidatorSet, err = b.Controller.LoadCommittee(b.LoadRootChainId(b.Height), b.RootHeight)
599599
if err != nil {

bft/election.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
/*
1010
ELECTION SORTITION:
1111
12-
1) Practical VRF: Hash(BLS.Signature(Last Proposers Addresses + CreatedHeight + Round)): a cryptographic
12+
1) Practical VRF: Hash(BLS.Signature(Last Proposers Addresses + Height + Round)): a cryptographic
1313
function that produces a random output that can be publicly verified. In BFT, each participant in
1414
the network uses their private key to create a digital signature against Sortition seed data which
1515
may be publicly verified using their Public Key.

controller/block.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ func (c *Controller) CommitCertificate(qc *lib.QuorumCertificate, block *lib.Blo
314314
go c.RCManager.Publish(id, info)
315315
}
316316
// update telemetry
317-
c.UpdateTelemetry(block, time.Since(start))
317+
defer c.UpdateTelemetry(qc, block, time.Since(start))
318318
// exit
319319
return
320320
}
@@ -411,6 +411,8 @@ func (c *Controller) HandlePeerBlock(msg *lib.BlockMessage, syncing bool) (*lib.
411411
// exit with error
412412
return nil, lib.ErrNoMaj23()
413413
}
414+
// update the non signer percent for the validators
415+
c.Metrics.UpdateNonSignerPercent(qc.Signature, v)
414416
}
415417
// ensure the proposal inside the quorum certificate is valid at a stateless level
416418
block, err := qc.CheckProposalBasic(c.FSM.Height(), c.Config.NetworkID, c.Config.ChainId)
@@ -505,13 +507,17 @@ func (c *Controller) SetFSMInConsensusModeForProposals() (reset func()) {
505507
}
506508

507509
// UpdateTelemetry() updates the prometheus metrics after 'committing' a block
508-
func (c *Controller) UpdateTelemetry(block *lib.Block, blockProcessingTime time.Duration) {
509-
// get the address of this node
510-
address := crypto.NewAddressFromBytes(c.Address)
510+
func (c *Controller) UpdateTelemetry(qc *lib.QuorumCertificate, block *lib.Block, blockProcessingTime time.Duration) {
511+
// create convenience variables
512+
address, vdfIterations := crypto.NewAddressFromBytes(c.Address), uint64(0)
513+
// attempt to get VDF iterations
514+
if block.BlockHeader.Vdf != nil {
515+
vdfIterations = block.BlockHeader.Vdf.Iterations
516+
}
511517
// update node metrics
512518
c.Metrics.UpdateNodeMetrics(c.isSyncing.Load())
513519
// update the block metrics
514-
c.Metrics.UpdateBlockMetrics(block.BlockHeader.ProposerAddress, len(block.Transactions), blockProcessingTime)
520+
c.Metrics.UpdateBlockMetrics(block.BlockHeader.ProposerAddress, uint64(len(qc.Block)), block.BlockHeader.NumTxs, vdfIterations, blockProcessingTime)
515521
// update validator metric
516522
if v, _ := c.FSM.GetValidator(address); v != nil && v.StakedAmount != 0 {
517523
c.Metrics.UpdateValidator(address.String(), v.StakedAmount, v.UnstakingHeight != 0, v.MaxPausedHeight != 0, v.Delegate, v.Compound)

controller/controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func New(fsm *fsm.StateMachine, c lib.Config, valKey crypto.PrivateKeyI, metrics
4545
return
4646
}
4747
// initialize the mempool using the FSM copy and the mempool config
48-
mempool, err := NewMempool(fsm, c.MempoolConfig, l)
48+
mempool, err := NewMempool(fsm, c.MempoolConfig, metrics, l)
4949
// if an error occurred when creating a new mempool
5050
if err != nil {
5151
// exit with error

controller/tx.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,15 +132,17 @@ type Mempool struct {
132132
FSM *fsm.StateMachine // the ephemeral finite state machine used to validate inbound transactions
133133
cachedResults lib.TxResults // a memory cache of transaction results for efficient verification
134134
cachedFailedTxs *lib.FailedTxCache // a memory cache of failed transactions for tracking
135+
metrics *lib.Metrics // telemetry
135136
log lib.LoggerI // the logger
136137
}
137138

138139
// NewMempool() creates a new instance of a Mempool structure
139-
func NewMempool(fsm *fsm.StateMachine, config lib.MempoolConfig, log lib.LoggerI) (m *Mempool, err lib.ErrorI) {
140+
func NewMempool(fsm *fsm.StateMachine, config lib.MempoolConfig, metrics *lib.Metrics, log lib.LoggerI) (m *Mempool, err lib.ErrorI) {
140141
// initialize the structure
141142
m = &Mempool{
142143
Mempool: lib.NewMempool(config),
143144
cachedFailedTxs: lib.NewFailedTxCache(),
145+
metrics: metrics,
144146
log: log,
145147
}
146148
// make an 'mempool (ephemeral copy) state' so the mempool can maintain only 'valid' transactions despite dependencies and conflicts
@@ -238,6 +240,8 @@ func (m *Mempool) checkMempool() {
238240
// delete the transaction
239241
m.DeleteTransaction(tx)
240242
}
243+
// update the mempool metrics
244+
m.metrics.UpdateMempoolMetrics(m.Mempool.TxCount(), m.Mempool.TxsBytes())
241245
}
242246

243247
// applyAndWriteTx() checks the validity of a transaction by playing it against the mempool (ephemeral copy) state machine

fsm/message.pb.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

fsm/state.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package fsm
33
import (
44
"runtime/debug"
55
"strings"
6+
"time"
67

78
"github.com/canopy-network/canopy/lib"
89
"github.com/canopy-network/canopy/lib/crypto"
@@ -155,6 +156,7 @@ func (s *StateMachine) ApplyTransactions(block *lib.Block) (txResultsList []*lib
155156
// define vars to track the bytes of the transaction results and the size of a block
156157
var (
157158
txResultsBytes [][]byte
159+
largestTxSize uint64
158160
blockSize uint64
159161
)
160162
// use a map to check for 'same-block' duplicate transactions
@@ -181,8 +183,15 @@ func (s *StateMachine) ApplyTransactions(block *lib.Block) (txResultsList []*lib
181183
txResultsList = append(txResultsList, result)
182184
// add the bytes to the list of transactions results
183185
txResultsBytes = append(txResultsBytes, txResultBz)
186+
// get the tx size
187+
txSize := uint64(len(tx))
184188
// add to the size of the block
185-
blockSize += uint64(len(tx))
189+
blockSize += txSize
190+
// see if the size is the largest
191+
if txSize > largestTxSize {
192+
// set as largest
193+
largestTxSize = txSize
194+
}
186195
// update the transaction count
187196
n++
188197
}
@@ -197,6 +206,8 @@ func (s *StateMachine) ApplyTransactions(block *lib.Block) (txResultsList []*lib
197206
}
198207
// create a transaction root for the block header
199208
root, _, err = lib.MerkleTree(txResultsBytes)
209+
// update metrics
210+
s.Metrics.UpdateLargestTxSize(largestTxSize)
200211
// return and exit
201212
return txResultsList, root, n, err
202213
}
@@ -332,6 +343,8 @@ func (s *StateMachine) GetMaxBlockSize() (uint64, lib.ErrorI) {
332343

333344
// GetRootChainInfo() returns the 'need-to-know' information for a nested chain
334345
func (s *StateMachine) GetRootChainInfo(id uint64) (*lib.RootChainInfo, lib.ErrorI) {
346+
// update the metrics once complete
347+
defer s.Metrics.UpdateGetRootChainInfo(time.Now())
335348
// get the previous state machine height
336349
lastSM, err := s.TimeMachine(s.Height() - 1)
337350
if err != nil {

lib/.proto/message.proto

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ message MessageEditOrder {
193193
// not modifiable, used for order identification only
194194
uint64 ChainId = 2; // @gotags: json:"chainID"
195195
// amount_for_sale: the updated amount of uCNPY listed for sale, a reduction will return escrowed tokens to the seller's
196-
// receive address
196+
// send address
197197
uint64 AmountForSale = 3; // @gotags: json:"amountForSale"
198198
// requested_amount: the updated amount of the 'counter asset' the buyer must send in order to complete a swap
199199
uint64 RequestedAmount = 4; // @gotags: json:"requestedAmount"

lib/.proto/swap.proto

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ message SellOrder {
4747
// committee: the id of the committee that is in-charge of escrow for the swap
4848
uint64 Committee = 2; // @gotags: json:"committee"
4949
// amount_for_sale: amount of CNPY for sale
50-
uint64 AmountForSale = 3; // @gotags: json:"amountForSalee"
50+
uint64 AmountForSale = 3; // @gotags: json:"amountForSale"
5151
// requested_amount: amount of 'counter-asset' to receive
5252
uint64 RequestedAmount = 4; // @gotags: json:"requestedAmount"
5353
// seller_receive_address: the external chain address to receive the 'counter-asset'

lib/certificate.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ func (x *QuorumCertificate) CheckProposalBasic(height, networkId, chainId uint64
156156
if err != nil {
157157
return nil, err
158158
}
159+
// ensure the block hash is equal
159160
if !bytes.Equal(x.BlockHash, blockHash) {
160161
return nil, ErrMismatchHeaderBlockHash()
161162
}

0 commit comments

Comments
 (0)