mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-03 03:35:19 +00:00
removing unnecessary formatting
This commit is contained in:
@@ -40,5 +40,7 @@ linters-settings:
|
||||
max-blank-identifiers: 3
|
||||
golint:
|
||||
min-confidence: 0
|
||||
maligned:
|
||||
suggest-new: true
|
||||
misspell:
|
||||
locale: US
|
||||
|
||||
@@ -31,7 +31,7 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi
|
||||
|
||||
### IMPROVEMENTS
|
||||
|
||||
- [config] \#9054 Flag added to overwrite abciresponses.
|
||||
- [config] \#9054 Configuration flag added to permit Tendermint to discard all ABCIResponses except for the most recent
|
||||
|
||||
### BUG FIXES
|
||||
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
Package server is used to start a new ABCI server.
|
||||
|
||||
It contains two server implementation:
|
||||
- gRPC server
|
||||
- socket server
|
||||
* gRPC server
|
||||
* socket server
|
||||
|
||||
*/
|
||||
package server
|
||||
|
||||
|
||||
@@ -410,7 +410,6 @@ func (pool *BlockPool) sendError(err error, peerID p2p.ID) {
|
||||
}
|
||||
|
||||
// for debugging purposes
|
||||
//
|
||||
//nolint:unused
|
||||
func (pool *BlockPool) debug() string {
|
||||
pool.mtx.Lock()
|
||||
|
||||
@@ -291,7 +291,7 @@ func (w *crashingWAL) Start() error { return w.next.Start() }
|
||||
func (w *crashingWAL) Stop() error { return w.next.Stop() }
|
||||
func (w *crashingWAL) Wait() { w.next.Wait() }
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------------
|
||||
type testSim struct {
|
||||
GenesisState sm.State
|
||||
Config *cfg.Config
|
||||
|
||||
@@ -978,9 +978,7 @@ func (cs *State) handleTxsAvailable() {
|
||||
// Used internally by handleTimeout and handleMsg to make state transitions
|
||||
|
||||
// Enter: `timeoutNewHeight` by startTime (commitTime+timeoutCommit),
|
||||
//
|
||||
// or, if SkipTimeoutCommit==true, after receiving all precommits from (height,round-1)
|
||||
//
|
||||
// Enter: `timeoutPrecommits` after any +2/3 precommits from (height,round-1)
|
||||
// Enter: +2/3 precommits for nil at (height,round-1)
|
||||
// Enter: +2/3 prevotes any or +2/3 precommits for block or any from (height, round)
|
||||
@@ -1062,9 +1060,7 @@ func (cs *State) needProofBlock(height int64) bool {
|
||||
|
||||
// Enter (CreateEmptyBlocks): from enterNewRound(height,round)
|
||||
// Enter (CreateEmptyBlocks, CreateEmptyBlocksInterval > 0 ):
|
||||
//
|
||||
// after enterNewRound(height,round), after timeout of CreateEmptyBlocksInterval
|
||||
//
|
||||
// Enter (!CreateEmptyBlocks) : after enterNewRound(height,round), once txs are in the mempool
|
||||
func (cs *State) enterPropose(height int64, round int32) {
|
||||
logger := cs.Logger.With("height", height, "round", round)
|
||||
|
||||
@@ -12,19 +12,19 @@ second pre-image attacks. Hence, use this library with caution.
|
||||
Otherwise you might run into similar issues as, e.g., in early Bitcoin:
|
||||
https://bitcointalk.org/?topic=102395
|
||||
|
||||
*
|
||||
/ \
|
||||
/ \
|
||||
/ \
|
||||
/ \
|
||||
* *
|
||||
/ \ / \
|
||||
/ \ / \
|
||||
/ \ / \
|
||||
* * * h6
|
||||
/ \ / \ / \
|
||||
h0 h1 h2 h3 h4 h5
|
||||
|
||||
*
|
||||
/ \
|
||||
/ \
|
||||
/ \
|
||||
/ \
|
||||
* *
|
||||
/ \ / \
|
||||
/ \ / \
|
||||
/ \ / \
|
||||
* * * h6
|
||||
/ \ / \ / \
|
||||
h0 h1 h2 h3 h4 h5
|
||||
TODO(ismail): add 2nd pre-image protection or clarify further on how we use this and why this secure.
|
||||
|
||||
*/
|
||||
package merkle
|
||||
|
||||
@@ -47,10 +47,10 @@ func HashFromByteSlices(items [][]byte) []byte {
|
||||
//
|
||||
// These preliminary results suggest:
|
||||
//
|
||||
// 1. The performance of the HashFromByteSlice is pretty good
|
||||
// 2. Go has low overhead for recursive functions
|
||||
// 3. The performance of the HashFromByteSlice routine is dominated
|
||||
// by the actual hashing of data
|
||||
// 1. The performance of the HashFromByteSlice is pretty good
|
||||
// 2. Go has low overhead for recursive functions
|
||||
// 3. The performance of the HashFromByteSlice routine is dominated
|
||||
// by the actual hashing of data
|
||||
//
|
||||
// Although this work is in no way exhaustive, point #3 suggests that
|
||||
// optimization of this routine would need to take an alternative
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
tmjson "github.com/tendermint/tendermint/libs/json"
|
||||
)
|
||||
|
||||
// -------------------------------------
|
||||
//-------------------------------------
|
||||
const (
|
||||
PrivKeyName = "tendermint/PrivKeySecp256k1"
|
||||
PubKeyName = "tendermint/PubKeySecp256k1"
|
||||
@@ -124,8 +124,8 @@ func GenPrivKeySecp256k1(secret []byte) PrivKey {
|
||||
|
||||
// used to reject malleable signatures
|
||||
// see:
|
||||
// - https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/signature_nocgo.go#L90-L93
|
||||
// - https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/crypto.go#L39
|
||||
// - https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/signature_nocgo.go#L90-L93
|
||||
// - https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/crypto.go#L39
|
||||
var secp256k1halfN = new(big.Int).Rsh(secp256k1.S256().N, 1)
|
||||
|
||||
// Sign creates an ECDSA signature on curve Secp256k1, using SHA256 on the msg.
|
||||
|
||||
@@ -3,7 +3,7 @@ Package evidence handles all evidence storage and gossiping from detection to bl
|
||||
For the different types of evidence refer to the `evidence.go` file in the types package
|
||||
or https://github.com/tendermint/spec/blob/master/spec/consensus/light-client/accountability.md.
|
||||
|
||||
# Gossiping
|
||||
Gossiping
|
||||
|
||||
The core functionality begins with the evidence reactor (see reactor.
|
||||
go) which operates both the sending and receiving of evidence.
|
||||
@@ -29,7 +29,7 @@ There are two buckets that evidence can be stored in: Pending & Committed.
|
||||
|
||||
All evidence is proto encoded to disk.
|
||||
|
||||
# Proposing
|
||||
Proposing
|
||||
|
||||
When a new block is being proposed (in state/execution.go#CreateProposalBlock),
|
||||
`PendingEvidence(maxBytes)` is called to send up to the maxBytes of uncommitted evidence, from the evidence store,
|
||||
@@ -42,11 +42,12 @@ Once the proposed evidence is submitted,
|
||||
the evidence is marked as committed and is moved from the broadcasted set to the committed set.
|
||||
As a result it is also removed from the concurrent list so that it is no longer gossiped.
|
||||
|
||||
# Minor Functionality
|
||||
Minor Functionality
|
||||
|
||||
As all evidence (including POLC's) are bounded by an expiration date, those that exceed this are no longer needed
|
||||
and hence pruned. Currently, only committed evidence in which a marker to the height that the evidence was committed
|
||||
and hence very small is saved. All updates are made from the `Update(block, state)` function which should be called
|
||||
when a new block is committed.
|
||||
|
||||
*/
|
||||
package evidence
|
||||
|
||||
@@ -102,13 +102,12 @@ func (evpool *Pool) verify(evidence types.Evidence) error {
|
||||
|
||||
// VerifyLightClientAttack verifies LightClientAttackEvidence against the state of the full node. This involves
|
||||
// the following checks:
|
||||
// - the common header from the full node has at least 1/3 voting power which is also present in
|
||||
// the conflicting header's commit
|
||||
// - 2/3+ of the conflicting validator set correctly signed the conflicting block
|
||||
// - the nodes trusted header at the same height as the conflicting header has a different hash
|
||||
// - the common header from the full node has at least 1/3 voting power which is also present in
|
||||
// the conflicting header's commit
|
||||
// - 2/3+ of the conflicting validator set correctly signed the conflicting block
|
||||
// - the nodes trusted header at the same height as the conflicting header has a different hash
|
||||
//
|
||||
// CONTRACT: must run ValidateBasic() on the evidence before verifying
|
||||
//
|
||||
// must check that the evidence has not expired (i.e. is outside the maximum age threshold)
|
||||
func VerifyLightClientAttack(e *types.LightClientAttackEvidence, commonHeader, trustedHeader *types.SignedHeader,
|
||||
commonVals *types.ValidatorSet, now time.Time, trustPeriod time.Duration) error {
|
||||
@@ -155,10 +154,10 @@ func VerifyLightClientAttack(e *types.LightClientAttackEvidence, commonHeader, t
|
||||
|
||||
// VerifyDuplicateVote verifies DuplicateVoteEvidence against the state of full node. This involves the
|
||||
// following checks:
|
||||
// - the validator is in the validator set at the height of the evidence
|
||||
// - the height, round, type and validator address of the votes must be the same
|
||||
// - the block ID's must be different
|
||||
// - The signatures must both be valid
|
||||
// - the validator is in the validator set at the height of the evidence
|
||||
// - the height, round, type and validator address of the votes must be the same
|
||||
// - the block ID's must be different
|
||||
// - The signatures must both be valid
|
||||
func VerifyDuplicateVote(e *types.DuplicateVoteEvidence, chainID string, valSet *types.ValidatorSet) error {
|
||||
_, val := valSet.GetByAddress(e.VoteA.ValidatorAddress)
|
||||
if val == nil {
|
||||
|
||||
@@ -17,7 +17,6 @@ const (
|
||||
// all other modules).
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// ParseLogLevel("consensus:debug,mempool:debug,*:error", log.NewTMLogger(os.Stdout), "info")
|
||||
func ParseLogLevel(lvl string, logger log.Logger, defaultLogLevelValue string) (log.Logger, error) {
|
||||
if lvl == "" {
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
const MaxLength = int(^uint(0) >> 1)
|
||||
|
||||
/*
|
||||
|
||||
CElement is an element of a linked-list
|
||||
Traversal from a CElement is goroutine-safe.
|
||||
|
||||
@@ -40,6 +41,7 @@ the for-loop. Use sync.Cond when you need serial access to the
|
||||
"condition". In our case our condition is if `next != nil || removed`,
|
||||
and there's no reason to serialize that condition for goroutines
|
||||
waiting on NextWait() (since it's just a read operation).
|
||||
|
||||
*/
|
||||
type CElement struct {
|
||||
mtx tmsync.RWMutex
|
||||
|
||||
@@ -68,7 +68,6 @@ func TestSmall(t *testing.T) {
|
||||
|
||||
// This test is quite hacky because it relies on SetFinalizer
|
||||
// which isn't guaranteed to run at all.
|
||||
//
|
||||
//nolint:unused,deadcode
|
||||
func _TestGCFifo(t *testing.T) {
|
||||
if runtime.GOARCH != "amd64" {
|
||||
@@ -118,7 +117,6 @@ func _TestGCFifo(t *testing.T) {
|
||||
|
||||
// This test is quite hacky because it relies on SetFinalizer
|
||||
// which isn't guaranteed to run at all.
|
||||
//
|
||||
//nolint:unused,deadcode
|
||||
func _TestGCRandom(t *testing.T) {
|
||||
if runtime.GOARCH != "amd64" {
|
||||
|
||||
@@ -39,10 +39,10 @@ type Monitor struct {
|
||||
// weight of each sample in the exponential moving average (EMA) calculation.
|
||||
// The exact formulas are:
|
||||
//
|
||||
// sampleTime = currentTime - prevSampleTime
|
||||
// sampleRate = byteCount / sampleTime
|
||||
// weight = 1 - exp(-sampleTime/windowSize)
|
||||
// newRate = weight*sampleRate + (1-weight)*oldRate
|
||||
// sampleTime = currentTime - prevSampleTime
|
||||
// sampleRate = byteCount / sampleTime
|
||||
// weight = 1 - exp(-sampleTime/windowSize)
|
||||
// newRate = weight*sampleRate + (1-weight)*oldRate
|
||||
//
|
||||
// The default values for sampleRate and windowSize (if <= 0) are 100ms and 1s,
|
||||
// respectively.
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
// compatibility with e.g. Javascript (which uses 64-bit floats for numbers, having 53-bit
|
||||
// precision):
|
||||
//
|
||||
// int32(32) // Output: 32
|
||||
// uint32(32) // Output: 32
|
||||
// int64(64) // Output: "64"
|
||||
// uint64(64) // Output: "64"
|
||||
// int(64) // Output: "64"
|
||||
// uint(64) // Output: "64"
|
||||
// int32(32) // Output: 32
|
||||
// uint32(32) // Output: 32
|
||||
// int64(64) // Output: "64"
|
||||
// uint64(64) // Output: "64"
|
||||
// int(64) // Output: "64"
|
||||
// uint(64) // Output: "64"
|
||||
//
|
||||
// Encoding of other scalars follows encoding/json:
|
||||
//
|
||||
@@ -50,7 +50,7 @@
|
||||
// Times are encoded as encoding/json, in RFC3339Nano format, but requiring UTC time zone (with zero
|
||||
// times emitted as "0001-01-01T00:00:00Z" as with encoding/json):
|
||||
//
|
||||
// time.Date(2020, 6, 8, 16, 21, 28, 123, time.FixedZone("UTC+2", 2*60*60))
|
||||
// time.Date(2020, 6, 8, 16, 21, 28, 123, time.FixedZone("UTC+2", 2*60*60))
|
||||
// // Output: "2020-06-08T14:21:28.000000123Z"
|
||||
// time.Time{} // Output: "0001-01-01T00:00:00Z"
|
||||
// (*time.Time)(nil) // Output: null
|
||||
@@ -95,4 +95,5 @@
|
||||
//
|
||||
// Struct{Car: &Car{Wheels: 4}, Vehicle: &Car{Wheels: 4}}
|
||||
// // Output: {"Car": {"Wheels: 4"}, "Vehicle": {"type":"vehicle/car","value":{"Wheels":4}}}
|
||||
//
|
||||
package json
|
||||
|
||||
@@ -69,19 +69,18 @@ func (l *filter) Error(msg string, keyvals ...interface{}) {
|
||||
// Allow*With methods, it is used as the logger's level.
|
||||
//
|
||||
// Examples:
|
||||
// logger = log.NewFilter(logger, log.AllowError(), log.AllowInfoWith("module", "crypto"))
|
||||
// logger.With("module", "crypto").Info("Hello") # produces "I... Hello module=crypto"
|
||||
//
|
||||
// logger = log.NewFilter(logger, log.AllowError(), log.AllowInfoWith("module", "crypto"))
|
||||
// logger.With("module", "crypto").Info("Hello") # produces "I... Hello module=crypto"
|
||||
// logger = log.NewFilter(logger, log.AllowError(),
|
||||
// log.AllowInfoWith("module", "crypto"),
|
||||
// log.AllowNoneWith("user", "Sam"))
|
||||
// logger.With("module", "crypto", "user", "Sam").Info("Hello") # returns nil
|
||||
//
|
||||
// logger = log.NewFilter(logger, log.AllowError(),
|
||||
// log.AllowInfoWith("module", "crypto"),
|
||||
// log.AllowNoneWith("user", "Sam"))
|
||||
// logger.With("module", "crypto", "user", "Sam").Info("Hello") # returns nil
|
||||
//
|
||||
// logger = log.NewFilter(logger,
|
||||
// log.AllowError(),
|
||||
// log.AllowInfoWith("module", "crypto"), log.AllowNoneWith("user", "Sam"))
|
||||
// logger.With("user", "Sam").With("module", "crypto").Info("Hello") # produces "I... Hello module=crypto user=Sam"
|
||||
// logger = log.NewFilter(logger,
|
||||
// log.AllowError(),
|
||||
// log.AllowInfoWith("module", "crypto"), log.AllowNoneWith("user", "Sam"))
|
||||
// logger.With("user", "Sam").With("module", "crypto").Info("Hello") # produces "I... Hello module=crypto user=Sam"
|
||||
func (l *filter) With(keyvals ...interface{}) Logger {
|
||||
keyInAllowedKeyvals := false
|
||||
|
||||
|
||||
@@ -22,9 +22,9 @@ type Logger interface {
|
||||
//
|
||||
// If w implements the following interface, so does the returned writer.
|
||||
//
|
||||
// interface {
|
||||
// Fd() uintptr
|
||||
// }
|
||||
// interface {
|
||||
// Fd() uintptr
|
||||
// }
|
||||
func NewSyncWriter(w io.Writer) io.Writer {
|
||||
return kitlog.NewSyncWriter(w)
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ func benchmarkRunnerKitlog(b *testing.B, logger kitlog.Logger, f func(kitlog.Log
|
||||
}
|
||||
}
|
||||
|
||||
// nolint: errcheck // ignore errors
|
||||
//nolint: errcheck // ignore errors
|
||||
var (
|
||||
baseMessage = func(logger kitlog.Logger) { logger.Log("foo_key", "foo_value") }
|
||||
withMessage = func(logger kitlog.Logger) { kitlog.With(logger, "a", "b").Log("d", "f") }
|
||||
|
||||
@@ -12,25 +12,25 @@
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// q, err := query.New("account.name='John'")
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// ctx, cancel := context.WithTimeout(context.Background(), 1 * time.Second)
|
||||
// defer cancel()
|
||||
// subscription, err := pubsub.Subscribe(ctx, "johns-transactions", q)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// q, err := query.New("account.name='John'")
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// ctx, cancel := context.WithTimeout(context.Background(), 1 * time.Second)
|
||||
// defer cancel()
|
||||
// subscription, err := pubsub.Subscribe(ctx, "johns-transactions", q)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// for {
|
||||
// select {
|
||||
// case msg <- subscription.Out():
|
||||
// // handle msg.Data() and msg.Events()
|
||||
// case <-subscription.Cancelled():
|
||||
// return subscription.Err()
|
||||
// }
|
||||
// }
|
||||
// for {
|
||||
// select {
|
||||
// case msg <- subscription.Out():
|
||||
// // handle msg.Data() and msg.Events()
|
||||
// case <-subscription.Cancelled():
|
||||
// return subscription.Err()
|
||||
// }
|
||||
// }
|
||||
package pubsub
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Package query provides a parser for a custom query format:
|
||||
//
|
||||
// abci.invoice.number=22 AND abci.invoice.owner=Ivan
|
||||
// abci.invoice.number=22 AND abci.invoice.owner=Ivan
|
||||
//
|
||||
// See query.peg for the grammar, which is a https://en.wikipedia.org/wiki/Parsing_expression_grammar.
|
||||
// More: https://github.com/PhilippeSigaud/Pegged/wiki/PEG-Basics
|
||||
|
||||
@@ -54,8 +54,7 @@ func (s *Subscription) Cancelled() <-chan struct{} {
|
||||
// If the channel is closed, Err returns a non-nil error explaining why:
|
||||
// - ErrUnsubscribed if the subscriber choose to unsubscribe,
|
||||
// - ErrOutOfCapacity if the subscriber is not pulling messages fast enough
|
||||
// and the channel returned by Out became full,
|
||||
//
|
||||
// and the channel returned by Out became full,
|
||||
// After Err returns a non-nil error, successive calls to Err return the same
|
||||
// error.
|
||||
func (s *Subscription) Err() error {
|
||||
|
||||
@@ -284,16 +284,16 @@ func (c *Client) restoreTrustedLightBlock() error {
|
||||
|
||||
// if options.Height:
|
||||
//
|
||||
// 1. ahead of trustedLightBlock.Height => fetch light blocks (same height as
|
||||
// 1) ahead of trustedLightBlock.Height => fetch light blocks (same height as
|
||||
// trustedLightBlock) from primary provider and check it's hash matches the
|
||||
// trustedLightBlock's hash (if not, remove trustedLightBlock and all the light blocks
|
||||
// before)
|
||||
//
|
||||
// 2. equals trustedLightBlock.Height => check options.Hash matches the
|
||||
// 2) equals trustedLightBlock.Height => check options.Hash matches the
|
||||
// trustedLightBlock's hash (if not, remove trustedLightBlock and all the light blocks
|
||||
// before)
|
||||
//
|
||||
// 3. behind trustedLightBlock.Height => remove all the light blocks between
|
||||
// 3) behind trustedLightBlock.Height => remove all the light blocks between
|
||||
// options.Height and trustedLightBlock.Height, update trustedLightBlock, then
|
||||
// check options.Hash matches the trustedLightBlock's hash (if not, remove
|
||||
// trustedLightBlock and all the light blocks before)
|
||||
@@ -395,10 +395,10 @@ func (c *Client) initializeWithTrustOptions(ctx context.Context, options TrustOp
|
||||
// TrustedLightBlock returns a trusted light block at the given height (0 - the latest).
|
||||
//
|
||||
// It returns an error if:
|
||||
// - there are some issues with the trusted store, although that should not
|
||||
// happen normally;
|
||||
// - negative height is passed;
|
||||
// - header has not been verified yet and is therefore not in the store
|
||||
// - there are some issues with the trusted store, although that should not
|
||||
// happen normally;
|
||||
// - negative height is passed;
|
||||
// - header has not been verified yet and is therefore not in the store
|
||||
//
|
||||
// Safe for concurrent use by multiple goroutines.
|
||||
func (c *Client) TrustedLightBlock(height int64) (*types.LightBlock, error) {
|
||||
@@ -510,9 +510,8 @@ func (c *Client) VerifyLightBlockAtHeight(ctx context.Context, height int64, now
|
||||
//
|
||||
// If the header, which is older than the currently trusted header, is
|
||||
// requested and the light client does not have it, VerifyHeader will perform:
|
||||
//
|
||||
// a) verifySkipping verification if nearest trusted header is found & not expired
|
||||
// b) backwards verification in all other cases
|
||||
// a) verifySkipping verification if nearest trusted header is found & not expired
|
||||
// b) backwards verification in all other cases
|
||||
//
|
||||
// It returns ErrOldHeaderExpired if the latest trusted header expired.
|
||||
//
|
||||
@@ -981,12 +980,12 @@ func (c *Client) backwards(
|
||||
// lightBlockFromPrimary retrieves the lightBlock from the primary provider
|
||||
// at the specified height. This method also handles provider behavior as follows:
|
||||
//
|
||||
// 1. If the provider does not respond or does not have the block, it tries again
|
||||
// with a different provider
|
||||
// 2. If all providers return the same error, the light client forwards the error to
|
||||
// where the initial request came from
|
||||
// 3. If the provider provides an invalid light block, is deemed unreliable or returns
|
||||
// any other error, the primary is permanently dropped and is replaced by a witness.
|
||||
// 1. If the provider does not respond or does not have the block, it tries again
|
||||
// with a different provider
|
||||
// 2. If all providers return the same error, the light client forwards the error to
|
||||
// where the initial request came from
|
||||
// 3. If the provider provides an invalid light block, is deemed unreliable or returns
|
||||
// any other error, the primary is permanently dropped and is replaced by a witness.
|
||||
func (c *Client) lightBlockFromPrimary(ctx context.Context, height int64) (*types.LightBlock, error) {
|
||||
c.providerMutex.Lock()
|
||||
l, err := c.primary.LightBlock(ctx, height)
|
||||
|
||||
@@ -109,9 +109,7 @@ func (c *Client) detectDivergence(ctx context.Context, primaryTrace []*types.Lig
|
||||
//
|
||||
// 1: errConflictingHeaders -> there may have been an attack on this light client
|
||||
// 2: errBadWitness -> the witness has either not responded, doesn't have the header or has given us an invalid one
|
||||
//
|
||||
// Note: In the case of an invalid header we remove the witness
|
||||
//
|
||||
// Note: In the case of an invalid header we remove the witness
|
||||
// 3: nil -> the hashes of the two headers match
|
||||
func (c *Client) compareNewHeaderWithWitness(ctx context.Context, errc chan error, h *types.SignedHeader,
|
||||
witness provider.Provider, witnessIndex int) {
|
||||
@@ -277,16 +275,16 @@ func (c *Client) handleConflictingHeaders(
|
||||
// it has received from another and preforms verifySkipping at the heights of each of the intermediate
|
||||
// headers in the trace until it reaches the divergentHeader. 1 of 2 things can happen.
|
||||
//
|
||||
// 1. The light client verifies a header that is different to the intermediate header in the trace. This
|
||||
// is the bifurcation point and the light client can create evidence from it
|
||||
// 2. The source stops responding, doesn't have the block or sends an invalid header in which case we
|
||||
// return the error and remove the witness
|
||||
// 1. The light client verifies a header that is different to the intermediate header in the trace. This
|
||||
// is the bifurcation point and the light client can create evidence from it
|
||||
// 2. The source stops responding, doesn't have the block or sends an invalid header in which case we
|
||||
// return the error and remove the witness
|
||||
//
|
||||
// CONTRACT:
|
||||
// 1. Trace can not be empty len(trace) > 0
|
||||
// 2. The last block in the trace can not be of a lower height than the target block
|
||||
// trace[len(trace)-1].Height >= targetBlock.Height
|
||||
// 3. The
|
||||
// 1. Trace can not be empty len(trace) > 0
|
||||
// 2. The last block in the trace can not be of a lower height than the target block
|
||||
// trace[len(trace)-1].Height >= targetBlock.Height
|
||||
// 3. The
|
||||
func (c *Client) examineConflictingHeaderAgainstTrace(
|
||||
ctx context.Context,
|
||||
trace []*types.LightBlock,
|
||||
|
||||
48
light/doc.go
48
light/doc.go
@@ -63,31 +63,29 @@ This package provides three major things:
|
||||
|
||||
Example usage:
|
||||
|
||||
db, err := dbm.NewGoLevelDB("light-client-db", dbDir)
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
|
||||
c, err := NewHTTPClient(
|
||||
chainID,
|
||||
TrustOptions{
|
||||
Period: 504 * time.Hour, // 21 days
|
||||
Height: 100,
|
||||
Hash: header.Hash(),
|
||||
},
|
||||
"http://localhost:26657",
|
||||
[]string{"http://witness1:26657"},
|
||||
dbs.New(db, ""),
|
||||
)
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
|
||||
h, err := c.TrustedHeader(100)
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
fmt.Println("header", h)
|
||||
db, err := dbm.NewGoLevelDB("light-client-db", dbDir)
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
c, err := NewHTTPClient(
|
||||
chainID,
|
||||
TrustOptions{
|
||||
Period: 504 * time.Hour, // 21 days
|
||||
Height: 100,
|
||||
Hash: header.Hash(),
|
||||
},
|
||||
"http://localhost:26657",
|
||||
[]string{"http://witness1:26657"},
|
||||
dbs.New(db, ""),
|
||||
)
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
h, err := c.TrustedHeader(100)
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
fmt.Println("header", h)
|
||||
|
||||
Check out other examples in example_test.go
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ var errNegOrZeroHeight = errors.New("negative or zero height")
|
||||
type KeyPathFunc func(path string, key []byte) (merkle.KeyPath, error)
|
||||
|
||||
// LightClient is an interface that contains functionality needed by Client from the light client.
|
||||
//
|
||||
//go:generate ../../scripts/mockery_generate.sh LightClient
|
||||
type LightClient interface {
|
||||
ChainID() string
|
||||
|
||||
@@ -19,13 +19,13 @@ var (
|
||||
// VerifyNonAdjacent verifies non-adjacent untrustedHeader against
|
||||
// trustedHeader. It ensures that:
|
||||
//
|
||||
// a) trustedHeader can still be trusted (if not, ErrOldHeaderExpired is returned)
|
||||
// b) untrustedHeader is valid (if not, ErrInvalidHeader is returned)
|
||||
// c) trustLevel ([1/3, 1]) of trustedHeaderVals (or trustedHeaderNextVals)
|
||||
// signed correctly (if not, ErrNewValSetCantBeTrusted is returned)
|
||||
// d) more than 2/3 of untrustedVals have signed h2
|
||||
// (otherwise, ErrInvalidHeader is returned)
|
||||
// e) headers are non-adjacent.
|
||||
// a) trustedHeader can still be trusted (if not, ErrOldHeaderExpired is returned)
|
||||
// b) untrustedHeader is valid (if not, ErrInvalidHeader is returned)
|
||||
// c) trustLevel ([1/3, 1]) of trustedHeaderVals (or trustedHeaderNextVals)
|
||||
// signed correctly (if not, ErrNewValSetCantBeTrusted is returned)
|
||||
// d) more than 2/3 of untrustedVals have signed h2
|
||||
// (otherwise, ErrInvalidHeader is returned)
|
||||
// e) headers are non-adjacent.
|
||||
//
|
||||
// maxClockDrift defines how much untrustedHeader.Time can drift into the
|
||||
// future.
|
||||
@@ -81,12 +81,12 @@ func VerifyNonAdjacent(
|
||||
// VerifyAdjacent verifies directly adjacent untrustedHeader against
|
||||
// trustedHeader. It ensures that:
|
||||
//
|
||||
// a) trustedHeader can still be trusted (if not, ErrOldHeaderExpired is returned)
|
||||
// b) untrustedHeader is valid (if not, ErrInvalidHeader is returned)
|
||||
// c) untrustedHeader.ValidatorsHash equals trustedHeader.NextValidatorsHash
|
||||
// d) more than 2/3 of new validators (untrustedVals) have signed h2
|
||||
// (otherwise, ErrInvalidHeader is returned)
|
||||
// e) headers are adjacent.
|
||||
// a) trustedHeader can still be trusted (if not, ErrOldHeaderExpired is returned)
|
||||
// b) untrustedHeader is valid (if not, ErrInvalidHeader is returned)
|
||||
// c) untrustedHeader.ValidatorsHash equals trustedHeader.NextValidatorsHash
|
||||
// d) more than 2/3 of new validators (untrustedVals) have signed h2
|
||||
// (otherwise, ErrInvalidHeader is returned)
|
||||
// e) headers are adjacent.
|
||||
//
|
||||
// maxClockDrift defines how much untrustedHeader.Time can drift into the
|
||||
// future.
|
||||
@@ -212,12 +212,12 @@ func HeaderExpired(h *types.SignedHeader, trustingPeriod time.Duration, now time
|
||||
// VerifyBackwards verifies an untrusted header with a height one less than
|
||||
// that of an adjacent trusted header. It ensures that:
|
||||
//
|
||||
// a) untrusted header is valid
|
||||
// b) untrusted header has a time before the trusted header
|
||||
// c) that the LastBlockID hash of the trusted header is the same as the hash
|
||||
// of the trusted header
|
||||
// a) untrusted header is valid
|
||||
// b) untrusted header has a time before the trusted header
|
||||
// c) that the LastBlockID hash of the trusted header is the same as the hash
|
||||
// of the trusted header
|
||||
//
|
||||
// For any of these cases ErrInvalidHeader is returned.
|
||||
// For any of these cases ErrInvalidHeader is returned.
|
||||
func VerifyBackwards(untrustedHeader, trustedHeader *types.Header) error {
|
||||
if err := untrustedHeader.ValidateBasic(); err != nil {
|
||||
return ErrInvalidHeader{err}
|
||||
|
||||
@@ -194,9 +194,7 @@ func (mem *CListMempool) TxsWaitChan() <-chan struct{} {
|
||||
|
||||
// It blocks if we're waiting on Update() or Reap().
|
||||
// cb: A callback from the CheckTx command.
|
||||
//
|
||||
// It gets called from another goroutine.
|
||||
//
|
||||
// It gets called from another goroutine.
|
||||
// CONTRACT: Either cb will get called, or err returned.
|
||||
//
|
||||
// Safe for concurrent use by multiple goroutines.
|
||||
@@ -312,7 +310,7 @@ func (mem *CListMempool) reqResCb(
|
||||
}
|
||||
|
||||
// Called from:
|
||||
// - resCbFirstTime (lock not held) if tx is valid
|
||||
// - resCbFirstTime (lock not held) if tx is valid
|
||||
func (mem *CListMempool) addTx(memTx *mempoolTx) {
|
||||
e := mem.txs.PushBack(memTx)
|
||||
mem.txsMap.Store(memTx.tx.Key(), e)
|
||||
@@ -321,8 +319,8 @@ func (mem *CListMempool) addTx(memTx *mempoolTx) {
|
||||
}
|
||||
|
||||
// Called from:
|
||||
// - Update (lock held) if tx was committed
|
||||
// - resCbRecheck (lock not held) if tx was invalidated
|
||||
// - Update (lock held) if tx was committed
|
||||
// - resCbRecheck (lock not held) if tx was invalidated
|
||||
func (mem *CListMempool) removeTx(tx types.Tx, elem *clist.CElement, removeFromCache bool) {
|
||||
mem.txs.Remove(elem)
|
||||
elem.DetachPrev()
|
||||
|
||||
45
node/doc.go
45
node/doc.go
@@ -6,34 +6,35 @@ Adding new p2p.Reactor(s)
|
||||
|
||||
To add a new p2p.Reactor, use the CustomReactors option:
|
||||
|
||||
node, err := NewNode(
|
||||
config,
|
||||
privVal,
|
||||
nodeKey,
|
||||
clientCreator,
|
||||
genesisDocProvider,
|
||||
dbProvider,
|
||||
metricsProvider,
|
||||
logger,
|
||||
CustomReactors(map[string]p2p.Reactor{"CUSTOM": customReactor}),
|
||||
)
|
||||
node, err := NewNode(
|
||||
config,
|
||||
privVal,
|
||||
nodeKey,
|
||||
clientCreator,
|
||||
genesisDocProvider,
|
||||
dbProvider,
|
||||
metricsProvider,
|
||||
logger,
|
||||
CustomReactors(map[string]p2p.Reactor{"CUSTOM": customReactor}),
|
||||
)
|
||||
|
||||
Replacing existing p2p.Reactor(s)
|
||||
|
||||
To replace the built-in p2p.Reactor, use the CustomReactors option:
|
||||
|
||||
node, err := NewNode(
|
||||
config,
|
||||
privVal,
|
||||
nodeKey,
|
||||
clientCreator,
|
||||
genesisDocProvider,
|
||||
dbProvider,
|
||||
metricsProvider,
|
||||
logger,
|
||||
CustomReactors(map[string]p2p.Reactor{"BLOCKCHAIN": customBlockchainReactor}),
|
||||
)
|
||||
node, err := NewNode(
|
||||
config,
|
||||
privVal,
|
||||
nodeKey,
|
||||
clientCreator,
|
||||
genesisDocProvider,
|
||||
dbProvider,
|
||||
metricsProvider,
|
||||
logger,
|
||||
CustomReactors(map[string]p2p.Reactor{"BLOCKCHAIN": customBlockchainReactor}),
|
||||
)
|
||||
|
||||
The list of existing reactors can be found in CustomReactors documentation.
|
||||
|
||||
*/
|
||||
package node
|
||||
|
||||
12
node/node.go
12
node/node.go
@@ -145,12 +145,12 @@ type blockSyncReactor interface {
|
||||
// WARNING: using any name from the below list of the existing reactors will
|
||||
// result in replacing it with the custom one.
|
||||
//
|
||||
// - MEMPOOL
|
||||
// - BLOCKCHAIN
|
||||
// - CONSENSUS
|
||||
// - EVIDENCE
|
||||
// - PEX
|
||||
// - STATESYNC
|
||||
// - MEMPOOL
|
||||
// - BLOCKCHAIN
|
||||
// - CONSENSUS
|
||||
// - EVIDENCE
|
||||
// - PEX
|
||||
// - STATESYNC
|
||||
func CustomReactors(reactors map[string]p2p.Reactor) Option {
|
||||
return func(n *Node) {
|
||||
for name, reactor := range reactors {
|
||||
|
||||
@@ -10,13 +10,9 @@ import (
|
||||
|
||||
// Only Go1.10 has a proper net.Conn implementation that
|
||||
// has the SetDeadline method implemented as per
|
||||
//
|
||||
// https://github.com/golang/go/commit/e2dd8ca946be884bb877e074a21727f1a685a706
|
||||
//
|
||||
// https://github.com/golang/go/commit/e2dd8ca946be884bb877e074a21727f1a685a706
|
||||
// lest we run into problems like
|
||||
//
|
||||
// https://github.com/tendermint/tendermint/issues/851
|
||||
//
|
||||
// https://github.com/tendermint/tendermint/issues/851
|
||||
// so for go versions < Go1.10 use our custom net.Conn creator
|
||||
// that doesn't return an `Unimplemented error` for net.Conn.
|
||||
// Before https://github.com/tendermint/tendermint/commit/49faa79bdce5663894b3febbf4955fb1d172df04
|
||||
|
||||
@@ -62,7 +62,6 @@ The byte id and the relative priorities of each `Channel` are configured upon
|
||||
initialization of the connection.
|
||||
|
||||
There are two methods for sending messages:
|
||||
|
||||
func (m MConnection) Send(chID byte, msgBytes []byte) bool {}
|
||||
func (m MConnection) TrySend(chID byte, msgBytes []byte}) bool {}
|
||||
|
||||
|
||||
@@ -94,16 +94,16 @@ func (ka *knownAddress) removeBucketRef(bucketIdx int) int {
|
||||
}
|
||||
|
||||
/*
|
||||
An address is bad if the address in question is a New address, has not been tried in the last
|
||||
minute, and meets one of the following criteria:
|
||||
An address is bad if the address in question is a New address, has not been tried in the last
|
||||
minute, and meets one of the following criteria:
|
||||
|
||||
1) It claims to be from the future
|
||||
2) It hasn't been seen in over a week
|
||||
3) It has failed at least three times and never succeeded
|
||||
4) It has failed ten times in the last week
|
||||
1) It claims to be from the future
|
||||
2) It hasn't been seen in over a week
|
||||
3) It has failed at least three times and never succeeded
|
||||
4) It has failed ten times in the last week
|
||||
|
||||
All addresses that meet these criteria are assumed to be worthless and not
|
||||
worth keeping hold of.
|
||||
All addresses that meet these criteria are assumed to be worthless and not
|
||||
worth keeping hold of.
|
||||
*/
|
||||
func (ka *knownAddress) isBad() bool {
|
||||
// Is Old --> good
|
||||
|
||||
@@ -58,7 +58,6 @@ func TestPEXReactorAddRemovePeer(t *testing.T) {
|
||||
}
|
||||
|
||||
// --- FAIL: TestPEXReactorRunning (11.10s)
|
||||
//
|
||||
// pex_reactor_test.go:411: expected all switches to be connected to at
|
||||
// least one peer (switches: 0 => {outbound: 1, inbound: 0}, 1 =>
|
||||
// {outbound: 0, inbound: 1}, 2 => {outbound: 0, inbound: 0}, )
|
||||
@@ -67,6 +66,7 @@ func TestPEXReactorAddRemovePeer(t *testing.T) {
|
||||
// if any peer (who we already connected to) has the same IP. Even though local
|
||||
// peers have different IP addresses, they all have the same underlying remote
|
||||
// IP: 127.0.0.1.
|
||||
//
|
||||
func TestPEXReactorRunning(t *testing.T) {
|
||||
N := 3
|
||||
switches := make([]*p2p.Switch, N)
|
||||
|
||||
@@ -379,8 +379,8 @@ func (sw *Switch) stopAndRemovePeer(peer Peer, reason interface{}) {
|
||||
// to the PEX/Addrbook to find the peer with the addr again
|
||||
// NOTE: this will keep trying even if the handshake or auth fails.
|
||||
// TODO: be more explicit with error types so we only retry on certain failures
|
||||
// - ie. if we're getting ErrDuplicatePeer we can stop
|
||||
// because the addrbook got us the peer back already
|
||||
// - ie. if we're getting ErrDuplicatePeer we can stop
|
||||
// because the addrbook got us the peer back already
|
||||
func (sw *Switch) reconnectToPeer(addr *NetAddress) {
|
||||
if sw.reconnecting.Has(string(addr.ID)) {
|
||||
return
|
||||
|
||||
@@ -72,7 +72,6 @@ func TestTrustMetricCopyNilPointer(t *testing.T) {
|
||||
}
|
||||
|
||||
// XXX: This test fails non-deterministically
|
||||
//
|
||||
//nolint:unused,deadcode
|
||||
func _TestTrustMetricStopPause(t *testing.T) {
|
||||
// The TestTicker will provide manual control over
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
/*
|
||||
|
||||
Package privval provides different implementations of the types.PrivValidator.
|
||||
|
||||
# FilePV
|
||||
FilePV
|
||||
|
||||
FilePV is the simplest implementation and developer default.
|
||||
It uses one file for the private key and another to store state.
|
||||
|
||||
# SignerListenerEndpoint
|
||||
SignerListenerEndpoint
|
||||
|
||||
SignerListenerEndpoint establishes a connection to an external process,
|
||||
like a Key Management Server (KMS), using a socket.
|
||||
@@ -14,14 +15,15 @@ SignerListenerEndpoint listens for the external KMS process to dial in.
|
||||
SignerListenerEndpoint takes a listener, which determines the type of connection
|
||||
(ie. encrypted over tcp, or unencrypted over unix).
|
||||
|
||||
# SignerDialerEndpoint
|
||||
SignerDialerEndpoint
|
||||
|
||||
SignerDialerEndpoint is a simple wrapper around a net.Conn. It's used by both IPCVal and TCPVal.
|
||||
|
||||
# SignerClient
|
||||
SignerClient
|
||||
|
||||
SignerClient handles remote validator connections that provide signing services.
|
||||
In production, it's recommended to wrap it with RetrySignerClient to avoid
|
||||
termination in case of temporary errors.
|
||||
|
||||
*/
|
||||
package privval
|
||||
|
||||
@@ -39,24 +39,24 @@ the example for more details.
|
||||
|
||||
Example:
|
||||
|
||||
c, err := New("http://192.168.1.10:26657", "/websocket")
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
c, err := New("http://192.168.1.10:26657", "/websocket")
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
|
||||
// call Start/Stop if you're subscribing to events
|
||||
err = c.Start()
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
defer c.Stop()
|
||||
// call Start/Stop if you're subscribing to events
|
||||
err = c.Start()
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
defer c.Stop()
|
||||
|
||||
res, err := c.Status()
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
res, err := c.Status()
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
|
||||
// handle result
|
||||
// handle result
|
||||
*/
|
||||
type HTTP struct {
|
||||
remote string
|
||||
|
||||
@@ -47,6 +47,7 @@ var _ client.Client = Client{}
|
||||
|
||||
// Call is used by recorders to save a call and response.
|
||||
// It can also be used to configure mock responses.
|
||||
//
|
||||
type Call struct {
|
||||
Name string
|
||||
Args interface{}
|
||||
|
||||
@@ -69,7 +69,7 @@ type peers interface {
|
||||
Peers() p2p.IPeerSet
|
||||
}
|
||||
|
||||
// ----------------------------------------------
|
||||
//----------------------------------------------
|
||||
// Environment contains objects and interfaces used by the RPC. It is expected
|
||||
// to be setup once during startup.
|
||||
type Environment struct {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// HTTP RPC server supporting calls via uri params, jsonrpc over HTTP, and jsonrpc over
|
||||
// websockets
|
||||
//
|
||||
// # Client Requests
|
||||
// Client Requests
|
||||
//
|
||||
// Suppose we want to expose the rpc function `HelloWorld(name string, num int)`.
|
||||
//
|
||||
@@ -9,12 +9,12 @@
|
||||
//
|
||||
// As a GET request, it would have URI encoded parameters, and look like:
|
||||
//
|
||||
// curl 'http://localhost:8008/hello_world?name="my_world"&num=5'
|
||||
// curl 'http://localhost:8008/hello_world?name="my_world"&num=5'
|
||||
//
|
||||
// Note the `'` around the url, which is just so bash doesn't ignore the quotes in `"my_world"`.
|
||||
// This should also work:
|
||||
//
|
||||
// curl http://localhost:8008/hello_world?name=\"my_world\"&num=5
|
||||
// curl http://localhost:8008/hello_world?name=\"my_world\"&num=5
|
||||
//
|
||||
// A GET request to `/` returns a list of available endpoints.
|
||||
// For those which take arguments, the arguments will be listed in order, with `_` where the actual value should be.
|
||||
@@ -23,19 +23,19 @@
|
||||
//
|
||||
// As a POST request, we use JSONRPC. For instance, the same request would have this as the body:
|
||||
//
|
||||
// {
|
||||
// "jsonrpc": "2.0",
|
||||
// "id": "anything",
|
||||
// "method": "hello_world",
|
||||
// "params": {
|
||||
// "name": "my_world",
|
||||
// "num": 5
|
||||
// }
|
||||
// }
|
||||
// {
|
||||
// "jsonrpc": "2.0",
|
||||
// "id": "anything",
|
||||
// "method": "hello_world",
|
||||
// "params": {
|
||||
// "name": "my_world",
|
||||
// "num": 5
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// With the above saved in file `data.json`, we can make the request with
|
||||
//
|
||||
// curl --data @data.json http://localhost:8008
|
||||
// curl --data @data.json http://localhost:8008
|
||||
//
|
||||
// WebSocket (JSONRPC)
|
||||
//
|
||||
@@ -43,42 +43,42 @@
|
||||
// Websocket connections are available at their own endpoint, typically `/websocket`,
|
||||
// though this is configurable when starting the server.
|
||||
//
|
||||
// # Server Definition
|
||||
// Server Definition
|
||||
//
|
||||
// Define some types and routes:
|
||||
//
|
||||
// type ResultStatus struct {
|
||||
// Value string
|
||||
// Value string
|
||||
// }
|
||||
//
|
||||
// Define some routes
|
||||
//
|
||||
// var Routes = map[string]*rpcserver.RPCFunc{
|
||||
// "status": rpcserver.NewRPCFunc(Status, "arg"),
|
||||
// }
|
||||
// var Routes = map[string]*rpcserver.RPCFunc{
|
||||
// "status": rpcserver.NewRPCFunc(Status, "arg"),
|
||||
// }
|
||||
//
|
||||
// An rpc function:
|
||||
//
|
||||
// func Status(v string) (*ResultStatus, error) {
|
||||
// return &ResultStatus{v}, nil
|
||||
// }
|
||||
// func Status(v string) (*ResultStatus, error) {
|
||||
// return &ResultStatus{v}, nil
|
||||
// }
|
||||
//
|
||||
// Now start the server:
|
||||
//
|
||||
// mux := http.NewServeMux()
|
||||
// rpcserver.RegisterRPCFuncs(mux, Routes)
|
||||
// wm := rpcserver.NewWebsocketManager(Routes)
|
||||
// mux.HandleFunc("/websocket", wm.WebsocketHandler)
|
||||
// logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
|
||||
// listener, err := rpc.Listen("0.0.0.0:8080", rpcserver.Config{})
|
||||
// if err != nil { panic(err) }
|
||||
// go rpcserver.Serve(listener, mux, logger)
|
||||
// mux := http.NewServeMux()
|
||||
// rpcserver.RegisterRPCFuncs(mux, Routes)
|
||||
// wm := rpcserver.NewWebsocketManager(Routes)
|
||||
// mux.HandleFunc("/websocket", wm.WebsocketHandler)
|
||||
// logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
|
||||
// listener, err := rpc.Listen("0.0.0.0:8080", rpcserver.Config{})
|
||||
// if err != nil { panic(err) }
|
||||
// go rpcserver.Serve(listener, mux, logger)
|
||||
//
|
||||
// Note that unix sockets are supported as well (eg. `/path/to/socket` instead of `0.0.0.0:8008`)
|
||||
// Now see all available endpoints by sending a GET request to `0.0.0.0:8008`.
|
||||
// Each route is available as a GET request, as a JSONRPCv2 POST request, and via JSONRPCv2 over websockets.
|
||||
//
|
||||
// # Examples
|
||||
// Examples
|
||||
//
|
||||
// - [Tendermint](https://github.com/tendermint/tendermint/blob/master/rpc/core/routes.go)
|
||||
package jsonrpc
|
||||
|
||||
@@ -176,7 +176,6 @@ func arrayParamsToArgs(
|
||||
// array.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// rpcFunc.args = [rpctypes.Context string]
|
||||
// rpcFunc.argNames = ["arg"]
|
||||
func jsonParamsToArgs(rpcFunc *RPCFunc, raw []byte) ([]reflect.Value, error) {
|
||||
|
||||
@@ -217,7 +217,7 @@ func (resp RPCResponse) String() string {
|
||||
// From the JSON-RPC 2.0 spec:
|
||||
//
|
||||
// If there was an error in detecting the id in the Request object (e.g. Parse
|
||||
// error/Invalid Request), it MUST be Null.
|
||||
// error/Invalid Request), it MUST be Null.
|
||||
func RPCParseError(err error) RPCResponse {
|
||||
return NewRPCErrorResponse(nil, -32700, "Parse error. Invalid JSON", err.Error())
|
||||
}
|
||||
@@ -225,7 +225,7 @@ func RPCParseError(err error) RPCResponse {
|
||||
// From the JSON-RPC 2.0 spec:
|
||||
//
|
||||
// If there was an error in detecting the id in the Request object (e.g. Parse
|
||||
// error/Invalid Request), it MUST be Null.
|
||||
// error/Invalid Request), it MUST be Null.
|
||||
func RPCInvalidRequestError(id jsonrpcid, err error) RPCResponse {
|
||||
return NewRPCErrorResponse(id, -32600, "Invalid Request", err.Error())
|
||||
}
|
||||
@@ -278,11 +278,8 @@ type Context struct {
|
||||
// RemoteAddr returns the remote address (usually a string "IP:port").
|
||||
// If neither HTTPReq nor WSConn is set, an empty string is returned.
|
||||
// HTTP:
|
||||
//
|
||||
// http.Request#RemoteAddr
|
||||
//
|
||||
// WS:
|
||||
//
|
||||
// result of GetRemoteAddr
|
||||
func (ctx *Context) RemoteAddr() string {
|
||||
if ctx.HTTPReq != nil {
|
||||
@@ -296,12 +293,9 @@ func (ctx *Context) RemoteAddr() string {
|
||||
// Context returns the request's context.
|
||||
// The returned context is always non-nil; it defaults to the background context.
|
||||
// HTTP:
|
||||
//
|
||||
// The context is canceled when the client's connection closes, the request
|
||||
// is canceled (with HTTP/2), or when the ServeHTTP method returns.
|
||||
//
|
||||
// WS:
|
||||
//
|
||||
// The context is canceled when the client's connections closes.
|
||||
func (ctx *Context) Context() context.Context {
|
||||
if ctx.HTTPReq != nil {
|
||||
@@ -314,7 +308,7 @@ func (ctx *Context) Context() context.Context {
|
||||
|
||||
//----------------------------------------
|
||||
// SOCKETS
|
||||
|
||||
//
|
||||
// Determine if its a unix or tcp socket.
|
||||
// If tcp, must specify the port; `0.0.0.0` will return incorrectly as "unix" since there's no port
|
||||
// TODO: deprecate
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
"github.com/tendermint/tendermint/version"
|
||||
)
|
||||
|
||||
// database key
|
||||
// database keys
|
||||
var (
|
||||
stateKey = []byte("stateKey")
|
||||
)
|
||||
|
||||
@@ -39,9 +39,7 @@ func calcABCIResponsesKey(height int64) []byte {
|
||||
|
||||
//----------------------
|
||||
|
||||
var (
|
||||
lastABCIResponseKey = []byte("lastABCIResponseKey")
|
||||
)
|
||||
var lastABCIResponseKey = []byte("lastABCIResponseKey")
|
||||
|
||||
//go:generate ../scripts/mockery_generate.sh Store
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@ import (
|
||||
BlockStore is a simple low level store for blocks.
|
||||
|
||||
There are three types of information stored:
|
||||
- BlockMeta: Meta information about each block
|
||||
- Block part: Parts of each block, aggregated w/ PartSet
|
||||
- Commit: The commit part of each block, for gossiping precommit votes
|
||||
- BlockMeta: Meta information about each block
|
||||
- Block part: Parts of each block, aggregated w/ PartSet
|
||||
- Commit: The commit part of each block, for gossiping precommit votes
|
||||
|
||||
Currently the precommit signatures are duplicated in the Block parts as
|
||||
well as the Commit. In the future this may change, perhaps by moving
|
||||
@@ -325,7 +325,6 @@ func (bs *BlockStore) PruneBlocks(height int64) (uint64, error) {
|
||||
// SaveBlock persists the given block, blockParts, and seenCommit to the underlying db.
|
||||
// blockParts: Must be parts of the block
|
||||
// seenCommit: The +2/3 precommits that were seen which committed at height.
|
||||
//
|
||||
// If all the nodes restart after committing a block,
|
||||
// we need this to reload the precommits to catch-up nodes to the
|
||||
// most recent height. Otherwise they'd stall at H-1.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// nolint: gosec
|
||||
// nolint:gosec
|
||||
package app
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// nolint: gosec
|
||||
//nolint: gosec
|
||||
package main
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// nolint: goconst
|
||||
//nolint: goconst
|
||||
package main
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// nolint: gosec
|
||||
//nolint: gosec
|
||||
package e2e
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// nolint: gosec
|
||||
//nolint: gosec
|
||||
package main
|
||||
|
||||
import (
|
||||
|
||||
@@ -200,7 +200,7 @@ func makeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) BlockID {
|
||||
|
||||
var nilBytes []byte
|
||||
|
||||
// This follows RFC-6962, i.e. `echo -n ” | sha256sum`
|
||||
// This follows RFC-6962, i.e. `echo -n ''| sha256sum`
|
||||
var emptyBytes = []byte{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8,
|
||||
0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b,
|
||||
0x78, 0x52, 0xb8, 0x55}
|
||||
|
||||
@@ -227,7 +227,7 @@ func (b *EventBus) PublishEventValidatorSetUpdates(data EventDataValidatorSetUpd
|
||||
return b.Publish(EventValidatorSetUpdates, data)
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
type NopEventBus struct{}
|
||||
|
||||
func (NopEventBus) Subscribe(
|
||||
|
||||
@@ -4,9 +4,9 @@ import "reflect"
|
||||
|
||||
// Go lacks a simple and safe way to see if something is a typed nil.
|
||||
// See:
|
||||
// - https://dave.cheney.net/2017/08/09/typed-nils-in-go-2
|
||||
// - https://groups.google.com/forum/#!topic/golang-nuts/wnH302gBa4I/discussion
|
||||
// - https://github.com/golang/go/issues/21538
|
||||
// - https://dave.cheney.net/2017/08/09/typed-nils-in-go-2
|
||||
// - https://groups.google.com/forum/#!topic/golang-nuts/wnH302gBa4I/discussion
|
||||
// - https://github.com/golang/go/issues/21538
|
||||
func isTypedNil(o interface{}) bool {
|
||||
rv := reflect.ValueOf(o)
|
||||
switch rv.Kind() {
|
||||
|
||||
@@ -411,18 +411,14 @@ func processChanges(origChanges []*Validator) (updates, removals []*Validator, e
|
||||
//
|
||||
// Inputs:
|
||||
// updates - a list of proper validator changes, i.e. they have been verified by processChanges for duplicates
|
||||
//
|
||||
// and invalid values.
|
||||
//
|
||||
// and invalid values.
|
||||
// vals - the original validator set. Note that vals is NOT modified by this function.
|
||||
// removedPower - the total voting power that will be removed after the updates are verified and applied.
|
||||
//
|
||||
// Returns:
|
||||
// tvpAfterUpdatesBeforeRemovals - the new total voting power if these updates would be applied without the removals.
|
||||
//
|
||||
// Note that this will be < 2 * MaxTotalVotingPower in case high power validators are removed and
|
||||
// validators are added/ updated with high power values.
|
||||
//
|
||||
// err - non-nil if the maximum allowed total voting power would be exceeded
|
||||
func verifyUpdates(
|
||||
updates []*Validator,
|
||||
@@ -473,7 +469,6 @@ func numNewValidators(updates []*Validator, vals *ValidatorSet) int {
|
||||
//
|
||||
// not the removals. It must be < 2*MaxTotalVotingPower and may be close to this limit if close to
|
||||
// MaxTotalVotingPower will be removed. This is still safe from overflow since MaxTotalVotingPower is maxInt64/8.
|
||||
//
|
||||
// No changes are made to the validator set 'vals'.
|
||||
func computeNewPriorities(updates []*Validator, vals *ValidatorSet, updatedTotalVotingPower int64) {
|
||||
for _, valUpdate := range updates {
|
||||
@@ -650,7 +645,6 @@ func (vals *ValidatorSet) updateWithChangeSet(changes []*Validator, allowDeletes
|
||||
// - applies the updates against the validator set
|
||||
// - applies the removals against the validator set
|
||||
// - performs scaling and centering of priority values
|
||||
//
|
||||
// If an error is detected during verification steps, it is returned and the validator set
|
||||
// is not changed.
|
||||
func (vals *ValidatorSet) UpdateWithChangeSet(changes []*Validator) error {
|
||||
|
||||
@@ -1641,7 +1641,7 @@ func TestValidatorSetProtoBuf(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------
|
||||
//---------------------
|
||||
// Sort validators by priority and address
|
||||
type validatorsByPriority []*Validator
|
||||
|
||||
@@ -1682,8 +1682,9 @@ func (tvals testValsByVotingPower) Swap(i, j int) {
|
||||
tvals[i], tvals[j] = tvals[j], tvals[i]
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
//-------------------------------------
|
||||
// Benchmark tests
|
||||
//
|
||||
func BenchmarkUpdates(b *testing.B) {
|
||||
const (
|
||||
n = 100
|
||||
|
||||
@@ -25,38 +25,38 @@ const (
|
||||
type P2PID string
|
||||
|
||||
/*
|
||||
VoteSet helps collect signatures from validators at each height+round for a
|
||||
predefined vote type.
|
||||
VoteSet helps collect signatures from validators at each height+round for a
|
||||
predefined vote type.
|
||||
|
||||
We need VoteSet to be able to keep track of conflicting votes when validators
|
||||
double-sign. Yet, we can't keep track of *all* the votes seen, as that could
|
||||
be a DoS attack vector.
|
||||
We need VoteSet to be able to keep track of conflicting votes when validators
|
||||
double-sign. Yet, we can't keep track of *all* the votes seen, as that could
|
||||
be a DoS attack vector.
|
||||
|
||||
There are two storage areas for votes.
|
||||
1. voteSet.votes
|
||||
2. voteSet.votesByBlock
|
||||
There are two storage areas for votes.
|
||||
1. voteSet.votes
|
||||
2. voteSet.votesByBlock
|
||||
|
||||
`.votes` is the "canonical" list of votes. It always has at least one vote,
|
||||
if a vote from a validator had been seen at all. Usually it keeps track of
|
||||
the first vote seen, but when a 2/3 majority is found, votes for that get
|
||||
priority and are copied over from `.votesByBlock`.
|
||||
`.votes` is the "canonical" list of votes. It always has at least one vote,
|
||||
if a vote from a validator had been seen at all. Usually it keeps track of
|
||||
the first vote seen, but when a 2/3 majority is found, votes for that get
|
||||
priority and are copied over from `.votesByBlock`.
|
||||
|
||||
`.votesByBlock` keeps track of a list of votes for a particular block. There
|
||||
are two ways a &blockVotes{} gets created in `.votesByBlock`.
|
||||
1. the first vote seen by a validator was for the particular block.
|
||||
2. a peer claims to have seen 2/3 majority for the particular block.
|
||||
`.votesByBlock` keeps track of a list of votes for a particular block. There
|
||||
are two ways a &blockVotes{} gets created in `.votesByBlock`.
|
||||
1. the first vote seen by a validator was for the particular block.
|
||||
2. a peer claims to have seen 2/3 majority for the particular block..
|
||||
|
||||
Since the first vote from a validator will always get added in `.votesByBlock`
|
||||
, all votes in `.votes` will have a corresponding entry in `.votesByBlock`.
|
||||
Since the first vote from a validator will always get added in `.votesByBlock`
|
||||
, all votes in `.votes` will have a corresponding entry in `.votesByBlock`.
|
||||
|
||||
When a &blockVotes{} in `.votesByBlock` reaches a 2/3 majority quorum, its
|
||||
votes are copied into `.votes`.
|
||||
When a &blockVotes{} in `.votesByBlock` reaches a 2/3 majority quorum, its
|
||||
votes are copied into `.votes`.
|
||||
|
||||
All this is memory bounded because conflicting votes only get added if a peer
|
||||
told us to track that block, each peer only gets to tell us 1 such block, and,
|
||||
there's only a limited number of peers.
|
||||
All this is memory bounded because conflicting votes only get added if a peer
|
||||
told us to track that block, each peer only gets to tell us 1 such block, and,
|
||||
there's only a limited number of peers.
|
||||
|
||||
NOTE: Assumes that the sum total of voting power does not exceed MaxUInt64.
|
||||
NOTE: Assumes that the sum total of voting power does not exceed MaxUInt64.
|
||||
*/
|
||||
type VoteSet struct {
|
||||
chainID string
|
||||
@@ -133,10 +133,8 @@ func (voteSet *VoteSet) Size() int {
|
||||
|
||||
// Returns added=true if vote is valid and new.
|
||||
// Otherwise returns err=ErrVote[
|
||||
//
|
||||
// UnexpectedStep | InvalidIndex | InvalidAddress |
|
||||
// InvalidSignature | InvalidBlockHash | ConflictingVotes ]
|
||||
//
|
||||
// UnexpectedStep | InvalidIndex | InvalidAddress |
|
||||
// InvalidSignature | InvalidBlockHash | ConflictingVotes ]
|
||||
// Duplicate votes return added=false, err=nil.
|
||||
// Conflicting votes return added=*, err=ErrVoteConflictingVotes.
|
||||
// NOTE: vote should not be mutated after adding.
|
||||
@@ -638,10 +636,10 @@ func (voteSet *VoteSet) MakeCommit() *Commit {
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Votes for a particular block
|
||||
There are two ways a *blockVotes gets created for a blockKey.
|
||||
1. first (non-conflicting) vote of a validator w/ blockKey (peerMaj23=false)
|
||||
2. A peer claims to have a 2/3 majority w/ blockKey (peerMaj23=true)
|
||||
Votes for a particular block
|
||||
There are two ways a *blockVotes gets created for a blockKey.
|
||||
1. first (non-conflicting) vote of a validator w/ blockKey (peerMaj23=false)
|
||||
2. A peer claims to have a 2/3 majority w/ blockKey (peerMaj23=true)
|
||||
*/
|
||||
type blockVotes struct {
|
||||
peerMaj23 bool // peer claims to have maj23
|
||||
|
||||
Reference in New Issue
Block a user