mirror of
https://github.com/luxfi/node.git
synced 2026-07-27 03:39:39 +00:00
Bump consensus v1.35.37 -> v1.36.1 + rip node-side view-change plumbing
v1.36 upstreamed round-scoped view-change INTO the engine (internal prevote/POL in attestation/reconcile/cert), dropping the external hooks config.Parameters. ViewChange + Runtime.HandleIncomingPrevote. Ripped the node's now-redundant external plumbing: the ViewChange enable block (LUX_CONSENSUS_VIEW_CHANGE gate), the quorumKindPrevote gossip routing + HandleIncomingPrevote call, the dead BroadcastPrevote gossiper method, and the quorumKindPrevote envelope kind. The engine owns view-change natively now (fail-secure halt on 2a-n>f unchanged). Whole node builds EXIT 0 on v1.36.1; luxd binary compiles (55M). Co-authored-by: Hanzo Dev <dev@hanzo.ai>
This commit is contained in:
+6
-41
@@ -1199,25 +1199,12 @@ func (m *manager) buildChain(chainParams ChainParameters, sb nets.Net) (*chainIn
|
||||
return nil, fmt.Errorf("refusing to start multi-node chain %s with non-BFT consensus params: %w", chainParams.ID, err)
|
||||
}
|
||||
}
|
||||
// Round-scoped view-change (restores liveness under competing siblings + a zero-margin
|
||||
// quorum — the 415→416 freeze). OPT-IN per deployment via LUX_CONSENSUS_VIEW_CHANGE=true
|
||||
// so devnet/testnet can enable it without a mainnet default (mainnet is owner-gated). Only
|
||||
// meaningful on a multi-validator (K>1) chain; K==1 has no competing proposers. The engine
|
||||
// itself fail-secure HALTS the view-change if the committee fails the 2α−n>f bound, so
|
||||
// enabling it can never weaken safety — at worst it halts (never forks).
|
||||
if consensusParams.K > 1 && strings.EqualFold(os.Getenv("LUX_CONSENSUS_VIEW_CHANGE"), "true") {
|
||||
consensusParams.ViewChange = true
|
||||
// NOTE: presetK/presetAlpha are the sample preset (MainnetParams K=21/α=15),
|
||||
// NOT the finality committee. The α-of-K cert and the view-change POL/precommit are
|
||||
// sized to the LIVE validator set at runtime via effectiveCommittee/bftCommittee
|
||||
// (e.g. 5 validators → K=5/α=4); the engine logs the effective (K,α) whenever it
|
||||
// re-clamps ("committee re-clamped … newK/newAlpha"). Do not read presetK as the quorum.
|
||||
m.Log.Info("round-scoped view-change ENABLED for chain",
|
||||
log.Stringer("chainID", chainParams.ID),
|
||||
log.Int("presetK", consensusParams.K),
|
||||
log.Int("presetAlpha", consensusParams.AlphaConfidence),
|
||||
log.String("note", "finality committee sized to the live validator set at runtime (see engine committee-clamp log for effective K/alpha)"))
|
||||
}
|
||||
// Round-scoped view-change (restores liveness under competing siblings + a
|
||||
// zero-margin quorum — the 415→416 freeze) is now owned INTERNALLY by the
|
||||
// consensus engine (v1.36+): the engine drives the prevote/POL tally + the
|
||||
// lock/unlock re-convergence natively and fail-secure HALTS if the committee
|
||||
// fails the 2α−n>f bound. The node no longer sets a ViewChange param or routes
|
||||
// prevotes — that external plumbing was upstreamed into the engine.
|
||||
_, innerIsDAGNative := vmTyped.(interface {
|
||||
Linearize(context.Context, ids.ID, chan<- vm.Message) error
|
||||
})
|
||||
@@ -3873,10 +3860,6 @@ func (b *blockHandler) Gossip(ctx context.Context, nodeID ids.NodeID, msg []byte
|
||||
b.engine.HandleIncomingVote(blockID, payload)
|
||||
case quorumKindCert:
|
||||
b.engine.HandleIncomingCert(payload)
|
||||
case quorumKindPrevote:
|
||||
// Round-scoped view-change prevote: the engine decodes+verifies
|
||||
// (height,round,canonical,sig) from the payload and tallies it toward a POL.
|
||||
b.engine.HandleIncomingPrevote(payload)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -4191,24 +4174,6 @@ func (g *networkGossiper) BroadcastVote(chainID ids.ID, networkID ids.ID, blockI
|
||||
return g.net.Gossip(msg, nil, g.networkID, -1, 0, 0).Len()
|
||||
}
|
||||
|
||||
// BroadcastPrevote sends this node's signed ROUND-SCOPED view-change prevote (the
|
||||
// non-binding preference signal) for `canonical` at (height, round) to ALL validators,
|
||||
// framed in a quorum envelope (kind 3) and decoded by blockHandler.Gossip into
|
||||
// engine.HandleIncomingPrevote. Prevotes never finalize anything — they drive the POL +
|
||||
// the lock/unlock rule that lets a competing-sibling split RE-CONVERGE (liveness under a
|
||||
// down proposer + zero-margin quorum). Only emitted when the chain runs params.ViewChange.
|
||||
func (g *networkGossiper) BroadcastPrevote(chainID ids.ID, networkID ids.ID, height uint64, round uint32, canonical ids.ID, voteBytes []byte) int {
|
||||
if g.net == nil || g.msgCreator == nil {
|
||||
return 0
|
||||
}
|
||||
envelope := encodeQuorumGossip(quorumKindPrevote, canonical, voteBytes)
|
||||
msg, err := g.msgCreator.Gossip(chainID, envelope)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return g.net.Gossip(msg, nil, g.networkID, -1, 0, 0).Len()
|
||||
}
|
||||
|
||||
// GossipCert broadcasts an assembled α-of-K finality cert to ALL validators so
|
||||
// followers finalize blockID on a verifiable proof (HandleIncomingCert), not a
|
||||
// fast-follow guess. Best effort: the gossiping node's own finality is already
|
||||
|
||||
+5
-9
@@ -374,17 +374,13 @@ func hashValidatorSet(set map[ids.NodeID]*validators.GetValidatorOutput) ids.ID
|
||||
//
|
||||
// kind 1 = signed vote (payload = engine encodeSignedVote: nodeID+sig)
|
||||
// kind 2 = finality cert (payload = engine cert MarshalBinary)
|
||||
// kind 3 = round-scoped view-change PREVOTE (payload = engine encodeSignedPrevote:
|
||||
// nodeID+height+round+canonical+sig, domain "LUX/chain/prevote/v1"). The
|
||||
// envelope blockID field carries the canonical for routing but is advisory —
|
||||
// HandleIncomingPrevote decodes the authoritative (height,round,canonical) from
|
||||
// the payload and verifies the signature over the reconstructed message.
|
||||
// (round-scoped view-change prevotes are engine-INTERNAL since consensus v1.36 —
|
||||
// the node no longer frames or routes a prevote kind)
|
||||
var quorumGossipMagic = [4]byte{'L', 'X', 'Q', 0x01}
|
||||
|
||||
const (
|
||||
quorumKindVote byte = 1
|
||||
quorumKindCert byte = 2
|
||||
quorumKindPrevote byte = 3
|
||||
quorumKindVote byte = 1
|
||||
quorumKindCert byte = 2
|
||||
)
|
||||
|
||||
// ErrNotQuorumGossip signals a payload is not a quorum envelope (so the caller
|
||||
@@ -410,7 +406,7 @@ func decodeQuorumGossip(data []byte) (kind byte, blockID ids.ID, payload []byte,
|
||||
kind = data[4]
|
||||
copy(blockID[:], data[5:5+32])
|
||||
payload = data[5+32:]
|
||||
if kind != quorumKindVote && kind != quorumKindCert && kind != quorumKindPrevote {
|
||||
if kind != quorumKindVote && kind != quorumKindCert {
|
||||
return 0, ids.Empty, nil, ErrNotQuorumGossip
|
||||
}
|
||||
return kind, blockID, payload, nil
|
||||
|
||||
@@ -26,7 +26,7 @@ require (
|
||||
github.com/huin/goupnp v1.3.0
|
||||
github.com/jackpal/gateway v1.1.1
|
||||
github.com/jackpal/go-nat-pmp v1.0.2
|
||||
github.com/luxfi/consensus v1.35.37
|
||||
github.com/luxfi/consensus v1.36.1
|
||||
github.com/luxfi/crypto v1.19.26
|
||||
github.com/luxfi/database v1.20.4
|
||||
github.com/luxfi/ids v1.3.1
|
||||
|
||||
@@ -315,8 +315,8 @@ github.com/luxfi/compress v0.0.5 h1:4tEUHw5MK1bu5UOjfYCt4OKMiH7yykIgmGPRA/BfJTM=
|
||||
github.com/luxfi/compress v0.0.5/go.mod h1:Cc1yxD2pfzrvpO32W2GDwLKff+CylHEvzZh2Ko8RSIU=
|
||||
github.com/luxfi/concurrent v0.0.3 h1:eJyv1fhaC0jMLMw6+QS774cUmp7GK+ouMgvLCqnC7cc=
|
||||
github.com/luxfi/concurrent v0.0.3/go.mod h1:Aj/FR5NpM0cB2P4Nt3+tz9+dV6V+LUW4HuMgSjwq5hw=
|
||||
github.com/luxfi/consensus v1.35.37 h1:y76OfTaNH13S7X5d4kDvnxdLM16wtSekDlBhKlPStL8=
|
||||
github.com/luxfi/consensus v1.35.37/go.mod h1:hmsGz3CcTrKxvw7/YSmfu8qAtzgyL5zQ3ajpUNcub/4=
|
||||
github.com/luxfi/consensus v1.36.1 h1:aHCUTgu0SaJXRouisQuFo1CkkdpHX0XftpM9GU07LzU=
|
||||
github.com/luxfi/consensus v1.36.1/go.mod h1:hmsGz3CcTrKxvw7/YSmfu8qAtzgyL5zQ3ajpUNcub/4=
|
||||
github.com/luxfi/constants v1.6.1 h1:4AfBh1YxDgnQjWPLqLpjiBaLAjPBw5naTTzRWWM19ms=
|
||||
github.com/luxfi/constants v1.6.1/go.mod h1:Pu5jWHdnUtQRbWC43yTUjU/pbIIKMDOd2a2yroSfo48=
|
||||
github.com/luxfi/container v0.0.4 h1:BXhF82WyfqVP5mjlNcr7tP0Fcnvl0Ap1rkiu+rq5XuM=
|
||||
@@ -427,8 +427,6 @@ github.com/luxfi/vm v1.2.5 h1:L1etY/gh68f9tns1BtyDUpZcBVqc3Ng1mqU3n38GyLo=
|
||||
github.com/luxfi/vm v1.2.5/go.mod h1:TCCg4lDcQFCjxaxfXnxPIrpRSVAyyf2ucT4A4w654Hg=
|
||||
github.com/luxfi/warp v1.24.0 h1:jrcJNlbOiZsAEopJMy9bSaCwI5NDZ8qgp/6sNoXqepg=
|
||||
github.com/luxfi/warp v1.24.0/go.mod h1:bKvTi24JHlANsl7qkWZAVr/DsMfvwy42f+Cc9x4+Sq8=
|
||||
github.com/luxfi/zap v0.8.11 h1:NIiZp/YyS1TQHfU/PHnMXynzPOKCfZOQssn5ytCdYXg=
|
||||
github.com/luxfi/zap v0.8.11/go.mod h1:JfqII8VtVQYLLTX6obU1DP9sjGqf9L24vfug5ifh0b8=
|
||||
github.com/luxfi/zapcodec v1.0.1 h1:pRxLxCOi6uihQMg8A8riDjNjefU2cXZxfRVZ+obeuL8=
|
||||
github.com/luxfi/zapcodec v1.0.1/go.mod h1:txrRt2JK4O76ssTxlXIwoNVsgzyZVL0ES4mlXqGNogs=
|
||||
github.com/luxfi/zapdb v1.10.1 h1:XV3k4UTTKKxUMgbfC7woPXgUEIJd3P5nj2lGTQ88xeE=
|
||||
|
||||
Reference in New Issue
Block a user