Documentation
¶
Overview ¶
Package upstream defines tm2 types whose amino wire-format is byte-identical to upstream Tendermint v0.34's protobuf encoding. They exist only for the privval-wire boundary — the path between a gno.land validator and an external upstream-protocol KMS such as tmkms.
The chain's own Vote/Proposal/BlockID/PartSetHeader types in tm2/pkg/bft/types remain unchanged; they're used in p2p messages and blocks, where any byte-level shift would be a network-coordinated upgrade. The translator (translator.go) converts between the two shapes.
CanonicalVote and CanonicalProposal are NOT redefined here — they live in tm2/pkg/bft/types and were re-tagged (POLRound varint; CanonicalPartSetHeader uint32 Total first) to be byte-identical to upstream's canonical.proto.
Index ¶
- Constants
- Variables
- func ProposalFromProto(p *upstreampb.Proposal) (*types.Proposal, error)
- func ProposalToProto(p *types.Proposal) (*upstreampb.Proposal, error)
- func PubKeyFromProto(p *upstreampb.PublicKey) (crypto.PubKey, error)
- func PubKeyToProto(pk crypto.PubKey) (*upstreampb.PublicKey, error)
- func ToTM2BlockID(b BlockID) types.BlockID
- func ToTM2PartSetHeader(p PartSetHeader) types.PartSetHeader
- func ToTM2Proposal(p *Proposal) *types.Proposal
- func ToTM2Vote(v *Vote) *types.Vote
- func UnwrapMsg(msg *upstreampb.Message) (interface{}, error)
- func VoteFromProto(v *upstreampb.Vote) (*types.Vote, error)
- func VoteToProto(v *types.Vote) (*upstreampb.Vote, error)
- func WrapMsg(pb interface{}) *upstreampb.Message
- type BlockID
- type DelimitedReader
- type DelimitedWriter
- type EndpointTimeoutError
- type PartSetHeader
- type Proposal
- type RetrySignerClient
- func (rsc *RetrySignerClient) Close() error
- func (rsc *RetrySignerClient) Init(maxWait time.Duration) error
- func (rsc *RetrySignerClient) IsConnected() bool
- func (rsc *RetrySignerClient) Ping() error
- func (rsc *RetrySignerClient) PubKey() crypto.PubKey
- func (rsc *RetrySignerClient) SignProposal(chainID string, proposal *types.Proposal) error
- func (rsc *RetrySignerClient) SignVote(chainID string, vote *types.Vote) error
- func (rsc *RetrySignerClient) WaitForConnection(maxWait time.Duration) error
- type SecretConnection
- func (sc *SecretConnection) Close() error
- func (sc *SecretConnection) LocalAddr() net.Addr
- func (sc *SecretConnection) Read(data []byte) (n int, err error)
- func (sc *SecretConnection) RemoteAddr() net.Addr
- func (sc *SecretConnection) RemotePubKey() crypto.PubKey
- func (sc *SecretConnection) SetDeadline(t time.Time) error
- func (sc *SecretConnection) SetReadDeadline(t time.Time) error
- func (sc *SecretConnection) SetWriteDeadline(t time.Time) error
- func (sc *SecretConnection) Write(data []byte) (n int, err error)
- type SignerClient
- func (sc *SignerClient) Close() error
- func (sc *SignerClient) Init(maxWait time.Duration) error
- func (sc *SignerClient) IsConnected() bool
- func (sc *SignerClient) Ping() error
- func (sc *SignerClient) PubKey() crypto.PubKey
- func (sc *SignerClient) SignProposal(chainID string, proposal *types.Proposal) error
- func (sc *SignerClient) SignVote(chainID string, vote *types.Vote) error
- func (sc *SignerClient) WaitForConnection(maxWait time.Duration) error
- type SignerListenerEndpoint
- func (se *SignerListenerEndpoint) Close() error
- func (se *SignerListenerEndpoint) ConnectionGeneration() uint64
- func (se *SignerListenerEndpoint) DropConnection()
- func (sl *SignerListenerEndpoint) EnsureConnectionLocked() error
- func (se *SignerListenerEndpoint) GetAvailableConnection(connectionAvailableCh chan net.Conn) bool
- func (se *SignerListenerEndpoint) IsConnected() bool
- func (sl *SignerListenerEndpoint) Lock()
- func (sl *SignerListenerEndpoint) OnStart() error
- func (sl *SignerListenerEndpoint) OnStop()
- func (se *SignerListenerEndpoint) ReadMessage() (*upstreampb.Message, error)
- func (sl *SignerListenerEndpoint) SendRequest(request *upstreampb.Message) (*upstreampb.Message, error)
- func (sl *SignerListenerEndpoint) SendRequestLocked(request *upstreampb.Message) (*upstreampb.Message, error)
- func (sl *SignerListenerEndpoint) SendRequestOnConnLocked(request *upstreampb.Message) (*upstreampb.Message, error)
- func (se *SignerListenerEndpoint) SetConnection(newConnection net.Conn)
- func (sl *SignerListenerEndpoint) Unlock()
- func (se *SignerListenerEndpoint) WaitConnection(connectionAvailableCh chan net.Conn, maxWait time.Duration, ...) error
- func (sl *SignerListenerEndpoint) WaitForConnection(maxWait time.Duration) error
- func (se *SignerListenerEndpoint) WriteMessage(msg *upstreampb.Message) (err error)
- type SignerListenerEndpointOption
- type TCPListener
- type TCPListenerOption
- type UnixListener
- type UnixListenerOption
- type Vote
- type WrappedRemoteSignerError
Constants ¶
const MaxRemoteSignerMsgSize = 1024 * 10
MaxRemoteSignerMsgSize bounds a single privval message. Mirrors cometbft/privval/signer_endpoint.go::maxRemoteSignerMsgSize. Larger messages are refused before allocation to prevent memory amplification.
const ProtocolVersion = "v0.34"
ProtocolVersion is the upstream Tendermint privval protocol dialect this package speaks. The wire types in upstreampb (Vote, Proposal, canonical sign-bytes layout) are hardcoded to v0.34 — the same value operators put in tmkms.toml's [[validator]].protocol_version. We expose it so config validation can refuse any other version (forward versions add fields that change canonical sign-bytes; we don't want to silently sign for a different dialect).
Variables ¶
var ( ErrConnectionTimeout = EndpointTimeoutError{} ErrNoConnection = errors.New("endpoint is not connected") ErrReadTimeout = errors.New("endpoint read timed out") ErrWriteTimeout = errors.New("endpoint write timed out") )
Socket errors.
var ( // ErrSmallOrderRemotePubKey is returned when the remote ephemeral // pubkey is one of the well-known small-order points (which would // collapse the DH shared secret to a known value). ErrSmallOrderRemotePubKey = errors.New("upstream: detected low order point from remote peer") )
var Package = pkg.NewPackage( "github.com/gnolang/gno/tm2/pkg/bft/privval/upstream", "upstream", pkg.GetCallersDirname(), ).WithTypes( Vote{}, Proposal{}, BlockID{}, PartSetHeader{}, )
Package registers the upstream-shaped operational types with amino so they can be marshaled via the codec. Registration drives the binary encoder's per-field FieldOptions (binary:"varint" tags), which is how these types produce upstream-Tendermint-compatible wire bytes.
NOTE: privval socket-protocol messages (Message, PubKeyRequest, etc.) are NOT amino-encoded. They live in the upstreampb sibling package as protoc-generated types, used directly via google.golang.org/protobuf for wire I/O. Mirrors how cometbft/privval uses cometbft/proto.
Functions ¶
func ProposalFromProto ¶
func ProposalFromProto(p *upstreampb.Proposal) (*types.Proposal, error)
func ProposalToProto ¶
func ProposalToProto(p *types.Proposal) (*upstreampb.Proposal, error)
func PubKeyFromProto ¶
func PubKeyFromProto(p *upstreampb.PublicKey) (crypto.PubKey, error)
PubKeyFromProto returns the tm2 crypto.PubKey for an upstreampb.PublicKey oneof, dispatching on the populated branch.
func PubKeyToProto ¶
func PubKeyToProto(pk crypto.PubKey) (*upstreampb.PublicKey, error)
PubKeyToProto converts a tm2 crypto.PubKey to the upstreampb.PublicKey oneof. Returns an error for unsupported key types — only ed25519 and secp256k1 are mapped, matching upstream Tendermint v0.34's PublicKey oneof.
func ToTM2BlockID ¶
func ToTM2PartSetHeader ¶
func ToTM2PartSetHeader(p PartSetHeader) types.PartSetHeader
func ToTM2Proposal ¶
ToTM2Proposal converts an upstream-shape Proposal back to chain-internal.
func ToTM2Vote ¶
ToTM2Vote converts an upstream-shape Vote back to a chain-internal types.Vote. ValidatorAddress bytes must be exactly crypto.AddressSize (20); otherwise the conversion panics — an upstream peer sending a malformed address is a protocol violation we surface immediately rather than silently truncate.
func UnwrapMsg ¶
func UnwrapMsg(msg *upstreampb.Message) (interface{}, error)
UnwrapMsg returns the concrete privval message inside an upstreampb.Message envelope. Returns an error if the envelope is empty or carries an unrecognized Sum variant — the wire was malformed or emitted by an incompatible peer.
func VoteFromProto ¶
func VoteFromProto(v *upstreampb.Vote) (*types.Vote, error)
VoteFromProto converts upstreampb.Vote to tm2 types.Vote.
func VoteToProto ¶
func VoteToProto(v *types.Vote) (*upstreampb.Vote, error)
VoteToProto converts a tm2 types.Vote to upstreampb.Vote.
Timestamp is ALWAYS emitted (even for the zero time, which becomes the protobuf year-0001 timestamp) because tendermint-rs / tmkms reject a SignVoteRequest with a missing Timestamp field. Both sides canonicalize the year-0001 case to the same bytes, so the signature still verifies.
func WrapMsg ¶
func WrapMsg(pb interface{}) *upstreampb.Message
WrapMsg builds an upstreampb.Message containing the given concrete privval message. Panics if pb is not one of the recognized privval message types — this is a programming error, not a runtime input.
Mirror of cometbft/privval/msgs.go::mustWrapMsg.
Types ¶
type BlockID ¶
type BlockID struct {
Hash []byte
PartSetHeader PartSetHeader
}
BlockID matches upstream's types.proto BlockID:
message BlockID {
bytes hash = 1;
PartSetHeader part_set_header = 2;
}
The Go field name is PartSetHeader (matching upstream) rather than tm2's PartsHeader. Only field POSITION matters for wire bytes.
func FromTM2BlockID ¶
type DelimitedReader ¶
type DelimitedReader struct {
// contains filtered or unexported fields
}
DelimitedReader reads varint-length-prefixed proto.Message values.
func NewDelimitedReader ¶
func NewDelimitedReader(r io.Reader, maxMsgSize int) *DelimitedReader
NewDelimitedReader reads directly from r (no buffering) and enforces the given per-message size cap. Use MaxRemoteSignerMsgSize for the privval path. It deliberately does NOT wrap r in a bufio.Reader: these readers are created fresh per message and discarded, and a buffered reader would slurp bytes belonging to the next frame (e.g. a coalesced TCP segment) and lose them when dropped — breaking the SecretConnection handshake intermittently.
type DelimitedWriter ¶
type DelimitedWriter struct {
// contains filtered or unexported fields
}
DelimitedWriter writes varint-length-prefixed proto.Message values.
func NewDelimitedWriter ¶
func NewDelimitedWriter(w io.Writer) *DelimitedWriter
NewDelimitedWriter wraps w. The caller is responsible for buffering / flushing if desired; this writer makes one Write per message.
type EndpointTimeoutError ¶
type EndpointTimeoutError struct{}
EndpointTimeoutError is returned when a privval endpoint times out waiting for a signer connection. Implements the net.Error interface.
func (EndpointTimeoutError) Error ¶
func (e EndpointTimeoutError) Error() string
func (EndpointTimeoutError) Temporary ¶
func (e EndpointTimeoutError) Temporary() bool
func (EndpointTimeoutError) Timeout ¶
func (e EndpointTimeoutError) Timeout() bool
type PartSetHeader ¶
PartSetHeader matches upstream's types.proto PartSetHeader:
message PartSetHeader {
uint32 total = 1;
bytes hash = 2;
}
Difference from tm2/pkg/bft/types.PartSetHeader:
- total: uint32 plain varint (tm2: int → sint64 zigzag)
Field order matches tm2 (Total first); only the type changes.
func FromTM2PartSetHeader ¶
func FromTM2PartSetHeader(p types.PartSetHeader) PartSetHeader
type Proposal ¶
type Proposal struct {
Type types.SignedMsgType
Height int64 `binary:"varint"`
Round int32 `binary:"varint"`
POLRound int32 `binary:"varint"`
BlockID BlockID
Timestamp time.Time
Signature []byte
}
Proposal matches upstream Tendermint v0.34's types.proto Proposal:
message Proposal {
SignedMsgType type = 1;
int64 height = 2;
int32 round = 3;
int32 pol_round = 4;
BlockID block_id = 5;
google.protobuf.Timestamp timestamp = 6;
bytes signature = 7;
}
func FromTM2Proposal ¶
FromTM2Proposal converts a chain-internal types.Proposal to upstream shape.
type RetrySignerClient ¶
type RetrySignerClient struct {
// contains filtered or unexported fields
}
RetrySignerClient wraps a SignerClient and retries on transient errors.
func NewRetrySignerClient ¶
func NewRetrySignerClient(sc *SignerClient, retries int, timeout time.Duration) *RetrySignerClient
NewRetrySignerClient returns a wrapper that retries each operation up to `retries` times with `timeout` sleep between attempts. If retries is 0, retries indefinitely (matches cometbft).
func (*RetrySignerClient) Close ¶
func (rsc *RetrySignerClient) Close() error
func (*RetrySignerClient) IsConnected ¶
func (rsc *RetrySignerClient) IsConnected() bool
func (*RetrySignerClient) Ping ¶
func (rsc *RetrySignerClient) Ping() error
func (*RetrySignerClient) PubKey ¶
func (rsc *RetrySignerClient) PubKey() crypto.PubKey
PubKey returns the cached pubkey from the inner client. Init must have been called on the wrapped client (or via this wrapper's Init). No retry needed — the cached value has no failure mode.
func (*RetrySignerClient) SignProposal ¶
func (rsc *RetrySignerClient) SignProposal(chainID string, proposal *types.Proposal) error
SignProposal mirrors SignVote.
func (*RetrySignerClient) SignVote ¶
func (rsc *RetrySignerClient) SignVote(chainID string, vote *types.Vote) error
SignVote retries on transient errors. RemoteSignerError (signer-side refusal, e.g. HRS regression detected by tmkms's consensus.json gate) passes through immediately — retrying a slashing-prevention refusal would be a serious bug.
func (*RetrySignerClient) WaitForConnection ¶
func (rsc *RetrySignerClient) WaitForConnection(maxWait time.Duration) error
type SecretConnection ¶
type SecretConnection struct {
// contains filtered or unexported fields
}
SecretConnection is a net.Conn that performs the upstream Tendermint v0.34 SecretConnection STS handshake (Merlin-bound) and then frames payloads with ChaCha20-Poly1305.
func MakeSecretConnection ¶
func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKey) (*SecretConnection, error)
MakeSecretConnection performs the upstream Tendermint v0.34 SecretConnection handshake over conn, identifying ourselves with locPrivKey. Returns an error on any handshake failure; the caller is responsible for closing conn in that case.
func (*SecretConnection) Close ¶
func (sc *SecretConnection) Close() error
net.Conn passthroughs — same semantics as the underlying conn.
func (*SecretConnection) LocalAddr ¶
func (sc *SecretConnection) LocalAddr() net.Addr
func (*SecretConnection) Read ¶
func (sc *SecretConnection) Read(data []byte) (n int, err error)
Read pulls one sealed frame off the conn, decrypts it, and copies up to len(data) bytes of payload into data. Excess payload is held in recvBuffer for the next Read call.
func (*SecretConnection) RemoteAddr ¶
func (sc *SecretConnection) RemoteAddr() net.Addr
func (*SecretConnection) RemotePubKey ¶
func (sc *SecretConnection) RemotePubKey() crypto.PubKey
RemotePubKey returns the authenticated remote pubkey.
func (*SecretConnection) SetDeadline ¶
func (sc *SecretConnection) SetDeadline(t time.Time) error
func (*SecretConnection) SetReadDeadline ¶
func (sc *SecretConnection) SetReadDeadline(t time.Time) error
func (*SecretConnection) SetWriteDeadline ¶
func (sc *SecretConnection) SetWriteDeadline(t time.Time) error
type SignerClient ¶
type SignerClient struct {
// contains filtered or unexported fields
}
SignerClient implements types.PrivValidator.
func NewSignerClient ¶
func NewSignerClient(endpoint *SignerListenerEndpoint, chainID string) (*SignerClient, error)
NewSignerClient constructs a client wrapping the given endpoint. The endpoint is started if it isn't running already. The validator's pubkey is fetched lazily via Init() (or implicitly on first SignVote) — see the doc on PubKey().
func (*SignerClient) Close ¶
func (sc *SignerClient) Close() error
Close shuts the endpoint down. It stops the endpoint's service — closing the listener, the ping loop and the service loop, and releasing the bound port — and drops the live conn (via OnStop). signerEndpoint.Close only drops the conn; stopping the service is required because node shutdown closes the validator through PrivValidator.Close (node.go), so a plain DropConnection would leave the listener, goroutines and port alive, blocking clean in-process restart. Idempotent: a second Close (or a Close before the endpoint was started) is a no-op.
func (*SignerClient) Init ¶
func (sc *SignerClient) Init(maxWait time.Duration) error
Init blocks for up to maxWait waiting for the signer to dial in, then fetches and caches the validator's consensus pubkey. Caller MUST call this (or otherwise populate the cache) before invoking PubKey() — the tm2 PrivValidator interface doesn't allow PubKey() to return an error, so we cache and panic on un-initialized access.
Typical startup flow: construct client, call Init(maxWait); from then on PubKey()/SignVote/SignProposal are safe.
func (*SignerClient) IsConnected ¶
func (sc *SignerClient) IsConnected() bool
IsConnected reports whether the endpoint has a live conn to the signer.
func (*SignerClient) Ping ¶
func (sc *SignerClient) Ping() error
Ping sends a PingRequest. Used by callers that want to test the live connection without doing a sign request. CometBFT's pingLoop already handles application-level keepalive; this is a manual-poke alternative.
func (*SignerClient) PubKey ¶
func (sc *SignerClient) PubKey() crypto.PubKey
PubKey returns the cached validator pubkey. Panics if not yet initialized — see Init().
func (*SignerClient) SignProposal ¶
func (sc *SignerClient) SignProposal(chainID string, proposal *types.Proposal) error
SignProposal mirrors SignVote for proposals — same echo verification applies (signer may only fill in Signature and canonicalize Timestamp), and identity is re-verified atomically with the sign request.
func (*SignerClient) SignVote ¶
func (sc *SignerClient) SignVote(chainID string, vote *types.Vote) error
SignVote sends the vote to the signer; on success only the Signature (and the canonicalized Timestamp) from the response are copied back into the caller's vote. Defense-in-depth: if a compromised or misbehaving signer returns a Vote with a different Height, Round, BlockID, or any other identifying field, we reject the response rather than letting the signer dictate WHAT we sign for. CometBFT's upstream `*vote = resp.Vote` convention conflates "trust the wire" with "trust the signer" — we don't.
The whole sequence (identity re-verification + sign request) runs under the endpoint's instance lock so a reconnect can't substitute a different signer between the pubkey check and the vote signing.
func (*SignerClient) WaitForConnection ¶
func (sc *SignerClient) WaitForConnection(maxWait time.Duration) error
WaitForConnection blocks for up to maxWait waiting for the signer to connect. Equivalent to endpoint.WaitForConnection — exposed for callers that want to gate startup on signer availability.
type SignerListenerEndpoint ¶
type SignerListenerEndpoint struct {
// contains filtered or unexported fields
}
SignerListenerEndpoint listens on a net.Listener for an external signer to dial in. Once connected, the connection is kept alive by sending PingRequest every (timeoutReadWrite * 2/3) and dropping/reconnecting on read/write timeout.
func NewSignerListenerEndpoint ¶
func NewSignerListenerEndpoint( logger *slog.Logger, listener net.Listener, options ...SignerListenerEndpointOption, ) *SignerListenerEndpoint
NewSignerListenerEndpoint constructs a listener endpoint over the given net.Listener. The listener should already be wrapped with any SecretConnection / mutual-auth layer the caller wants — see socket_listener.go for the standard wrapper.
func (*SignerListenerEndpoint) Close ¶
func (se *SignerListenerEndpoint) Close() error
Close drops the underlying conn. Idempotent.
func (*SignerListenerEndpoint) ConnectionGeneration ¶
func (se *SignerListenerEndpoint) ConnectionGeneration() uint64
ConnectionGeneration returns a counter that increments every time a new conn is installed. Used by SignerClient to spot a reconnect and re-verify the signer's identity before signing for it.
func (*SignerListenerEndpoint) DropConnection ¶
func (se *SignerListenerEndpoint) DropConnection()
DropConnection closes and clears the held conn. Idempotent.
func (*SignerListenerEndpoint) EnsureConnectionLocked ¶
func (sl *SignerListenerEndpoint) EnsureConnectionLocked() error
EnsureConnectionLocked exposes the conn-establishment step so callers (notably SignerClient.SignVote / SignProposal) can run their identity verification AFTER a fresh conn is installed. Without this split, a DropConnection that leaves connGen unchanged would let verifyIdentityLocked's gen short-circuit pass (currentGen == verifiedGen) before ensureConnection bumps the gen on a re-dial, producing a TOCTOU window where a swapped signer's response is accepted under the old cached identity.
Caller MUST hold the lock via Lock(). Uses the endpoint's timeoutAccept as the wait budget.
func (*SignerListenerEndpoint) GetAvailableConnection ¶
GetAvailableConnection retrieves a queued conn if one is ready, without blocking. Returns true if a conn was claimed.
func (*SignerListenerEndpoint) IsConnected ¶
func (se *SignerListenerEndpoint) IsConnected() bool
IsConnected reports whether a live conn is held.
func (*SignerListenerEndpoint) Lock ¶
func (sl *SignerListenerEndpoint) Lock()
Lock and Unlock expose the per-instance mutex so callers can bracket a multi-RPC sequence atomically (e.g., SignerClient does PubKeyRequest + SignVoteRequest under one lock so a reconnect can't sneak a different signer in between the identity check and the vote signing). Pair with SendRequestLocked.
func (*SignerListenerEndpoint) OnStart ¶
func (sl *SignerListenerEndpoint) OnStart() error
OnStart implements service.Service.
func (*SignerListenerEndpoint) OnStop ¶
func (sl *SignerListenerEndpoint) OnStop()
OnStop implements service.Service.
Closes stopCh BEFORE acquiring instanceMtx so a pending WaitForConnection (which has released instanceMtx for its blocking wait) can observe the stop and return promptly. Without this, an operator-recommended Init(60s) wait would pin Stop() for the full timeout if no signer dialed in.
func (*SignerListenerEndpoint) ReadMessage ¶
func (se *SignerListenerEndpoint) ReadMessage() (*upstreampb.Message, error)
ReadMessage reads one privval message from the held conn, applying the configured read deadline. On ANY error (timeout, peer EOF, closed conn, decode failure) the conn is dropped so the next read forces a reconnect — leaving a half-dead conn live would have IsConnected() lie and skip the reconnect path on the next SendRequest.
The pointer return shape is dictated by upstreampb.Message embedding google.golang.org/protobuf/runtime/protoimpl.MessageState (which itself contains a sync.Mutex). Passing or returning Message by value would trip govet's copylocks check.
func (*SignerListenerEndpoint) SendRequest ¶
func (sl *SignerListenerEndpoint) SendRequest(request *upstreampb.Message) (*upstreampb.Message, error)
SendRequest writes one privval message and reads the response. Used by SignerClient for PubKeyRequest / SignVoteRequest / etc.
Resets the ping timer on success — successful traffic counts as a keepalive, no need to send an explicit ping right after.
func (*SignerListenerEndpoint) SendRequestLocked ¶
func (sl *SignerListenerEndpoint) SendRequestLocked(request *upstreampb.Message) (*upstreampb.Message, error)
SendRequestLocked is SendRequest without taking the instance mutex. Caller MUST hold the lock via Lock().
func (*SignerListenerEndpoint) SendRequestOnConnLocked ¶
func (sl *SignerListenerEndpoint) SendRequestOnConnLocked(request *upstreampb.Message) (*upstreampb.Message, error)
SendRequestOnConnLocked writes and reads on the held conn. Does NOT call ensureConnection — callers that need that should pair this with EnsureConnectionLocked. Caller MUST hold the lock.
func (*SignerListenerEndpoint) SetConnection ¶
SetConnection installs a new conn, replacing any previously held one.
func (*SignerListenerEndpoint) Unlock ¶
func (sl *SignerListenerEndpoint) Unlock()
func (*SignerListenerEndpoint) WaitConnection ¶
func (se *SignerListenerEndpoint) WaitConnection(connectionAvailableCh chan net.Conn, maxWait time.Duration, stopCh <-chan struct{}) error
WaitConnection blocks for up to maxWait waiting for a queued conn, returning ErrConnectionTimeout if none arrives in time. If stopCh is non-nil and gets closed before the conn or timeout, the wait also returns ErrConnectionTimeout — callers thread the owning endpoint's stop signal so SendRequest / WaitForConnection unblock promptly when the service is stopping rather than pinning the caller (and instanceMtx) for the full maxWait.
func (*SignerListenerEndpoint) WaitForConnection ¶
func (sl *SignerListenerEndpoint) WaitForConnection(maxWait time.Duration) error
WaitForConnection blocks for up to maxWait waiting for a connected signer. Returns ErrConnectionTimeout if no signer connects in time or the endpoint is stopped.
Validator startup typically calls this once before consensus begins, so the validator's identity (returned by SignerClient.GetPubKey()) is available before the first vote is needed.
instanceMtx is held only for the synchronous "check connected / trigger connect" step — the blocking wait runs without the lock so OnStop can take it and proceed.
func (*SignerListenerEndpoint) WriteMessage ¶
func (se *SignerListenerEndpoint) WriteMessage(msg *upstreampb.Message) (err error)
WriteMessage writes one privval message to the held conn, applying the configured write deadline. On ANY error the conn is dropped. msg must be non-nil. Same rationale as ReadMessage — a partially-written stream after EOF/ErrClosed cannot be recovered, so the next caller must see "not connected" and trigger reconnect.
type SignerListenerEndpointOption ¶
type SignerListenerEndpointOption func(*SignerListenerEndpoint)
SignerListenerEndpointOption is an optional parameter passed to the constructor. Mirrors the cometbft pattern.
func SignerListenerEndpointTimeoutReadWrite ¶
func SignerListenerEndpointTimeoutReadWrite(timeout time.Duration) SignerListenerEndpointOption
SignerListenerEndpointTimeoutReadWrite sets the read/write deadline on the held conn (default 5s). The ping interval is derived as (timeout * 2/3).
type TCPListener ¶
type TCPListener struct {
*net.TCPListener
// contains filtered or unexported fields
}
TCPListener wraps a net.TCPListener with privval timeouts, SecretConnection encryption, and a mutual-auth allowlist. Accept returns an encrypted net.Conn whose remote pubkey is guaranteed to be in authorizedKeys.
func NewTCPListener ¶
func NewTCPListener( ln *net.TCPListener, secretConnKey ed25519.PrivKeyEd25519, authorizedKeys []ed25519.PubKeyEd25519, opts ...TCPListenerOption, ) *TCPListener
NewTCPListener wraps ln. secretConnKey is the validator's identity (typically the node_id key). authorizedKeys is the allowlist of expected signer pubkeys (typically a single tmkms identity, or multiple cosigners for Horcrux). An empty allowlist accepts ANY peer that completes the SecretConnection handshake — equivalent to gnokms's "fail-open" mode and recommended only for dev/test.
func (*TCPListener) Accept ¶
func (ln *TCPListener) Accept() (net.Conn, error)
Accept implements net.Listener. Sets the configured accept deadline, performs the SecretConnection handshake (which validates the remote peer signed a fresh challenge with its claimed pubkey), then verifies the remote pubkey is in the allowlist. Connections failing any of these are dropped before being returned.
type TCPListenerOption ¶
type TCPListenerOption func(*TCPListener)
TCPListenerOption sets an optional parameter on the TCPListener.
func TCPListenerTimeoutAccept ¶
func TCPListenerTimeoutAccept(timeout time.Duration) TCPListenerOption
TCPListenerTimeoutAccept sets the per-Accept deadline. Zero disables.
func TCPListenerTimeoutReadWrite ¶
func TCPListenerTimeoutReadWrite(timeout time.Duration) TCPListenerOption
TCPListenerTimeoutReadWrite sets the read/write deadline applied to each accepted connection.
type UnixListener ¶
type UnixListener struct {
*net.UnixListener
// contains filtered or unexported fields
}
UnixListener wraps a net.UnixListener with privval timeouts. UDS does NOT layer SecretConnection — kernel-level isolation suffices for same-host privval. Operators must protect the socket via filesystem perms.
func NewUnixListener ¶
func NewUnixListener(ln *net.UnixListener, opts ...UnixListenerOption) *UnixListener
NewUnixListener wraps ln (a *net.UnixListener).
type UnixListenerOption ¶
type UnixListenerOption func(*UnixListener)
UnixListenerOption sets an optional parameter on the UnixListener.
func UnixListenerTimeoutAccept ¶
func UnixListenerTimeoutAccept(timeout time.Duration) UnixListenerOption
UnixListenerTimeoutAccept sets the per-Accept deadline.
func UnixListenerTimeoutReadWrite ¶
func UnixListenerTimeoutReadWrite(timeout time.Duration) UnixListenerOption
UnixListenerTimeoutReadWrite sets the read/write deadline applied to each accepted connection.
type Vote ¶
type Vote struct {
Type types.SignedMsgType
Height int64 `binary:"varint"`
Round int32 `binary:"varint"`
BlockID BlockID
Timestamp time.Time
ValidatorAddress []byte
ValidatorIndex int32 `binary:"varint"`
Signature []byte
}
Vote matches upstream Tendermint v0.34's types.proto Vote message:
message Vote {
SignedMsgType type = 1;
int64 height = 2;
int32 round = 3;
BlockID block_id = 4;
google.protobuf.Timestamp timestamp = 5;
bytes validator_address = 6;
int32 validator_index = 7;
bytes signature = 8;
}
Differences from tm2/pkg/bft/types.Vote:
- height: int64 plain varint (tm2: sint64 zigzag)
- round: int32 plain varint (tm2: sint64)
- validator_address: raw bytes (tm2: bech32 string via Address.MarshalAmino)
- validator_index: int32 plain varint (tm2: sint64)
func FromTM2Vote ¶
FromTM2Vote converts a chain-internal types.Vote to its upstream-compatible shape. ValidatorAddress is the raw 20 bytes of the bech32-encoded tm2 Address; rounds and indices narrow to int32 (overflow panics — these are consensus-shaped values that cannot legitimately exceed int32 range).
type WrappedRemoteSignerError ¶
WrappedRemoteSignerError allows the local side to surface a privval RemoteSignerError (returned over the wire by tmkms) as a Go error.
Mirrors cometbft/privval/errors.go::RemoteSignerError. Distinct from upstreampb.RemoteSignerError (the wire-level message) — this is the Go-level error type the validator code sees after unwrapping.
func (*WrappedRemoteSignerError) Error ¶
func (e *WrappedRemoteSignerError) Error() string