Documentation
¶
Index ¶
- Variables
- type Config
- type PersistEntry
- type Pool
- func (p *Pool) Close() error
- func (p *Pool) Forget(c cid.Cid)
- func (p *Pool) Pending() []*ltypes.SignedMessage
- func (p *Pool) Publish(ctx context.Context, sm *ltypes.SignedMessage) (cid.Cid, error)
- func (p *Pool) Reconcile(ctx context.Context, headEpoch int64, search SearchFunc)
- func (p *Pool) Stats() Stats
- type SearchFunc
- type SearchResult
- type Stats
Constants ¶
This section is empty.
Variables ¶
var ErrDryRun = errors.New("mpool: dry-run mode, not publishing")
ErrDryRun is returned by Pool.Publish when DryRun is true.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// Topic name. Defaults to build.MainnetGossipTopicMessages.
Topic string
// DryRun: when true, Publish validates locally and records the
// would-be publish but doesn't actually push to gossipsub. Useful
// for production safety while we shake out the libp2p mesh.
DryRun bool
// OnMessage is fired for every signed message received from the
// network. Nil means "ignore incoming traffic".
OnMessage func(*ltypes.SignedMessage, peer.ID)
// --- #47: pending confirm + rebroadcast loop ---
//
// ConfirmAfterEpochs is the confidence window: a published message not
// seen on chain for at least this many epochs is rebroadcast (identical
// bytes, same nonce/CID). Default 3 (~90s mainnet). Long enough that a
// slow-but-valid inclusion isn't mistaken for failure.
ConfirmAfterEpochs int64
// MaxRetries caps rebroadcasts before a message is marked failed.
// Default 5. 0 uses the default; use a negative value for "unlimited".
MaxRetries int
// OnFailed, if set, is invoked once when a pending message gives up
// (max retries exhausted). The message is also moved to a failed set
// observable via Stats.Failed. Never silently stuck.
OnFailed func(*ltypes.SignedMessage, string)
// --- #119: durable pending-message store ---
//
// PersistPath is the on-disk JSONL journal Lantern uses to keep the
// pending set alive across daemon restart. When empty (the historical
// default), the pool is memory-only and behaves like pre-#119.
//
// When set:
// - New() opens the file, replays the journal, and re-registers every
// live entry into the in-memory pending set. Nonce derivation
// (MpoolGetNonce) reads Pending() so a restart transparently keeps
// each account's next nonce correct.
// - Publish() fsyncs an "add" line before returning success.
// - Reconcile confirm/fail branches fsync a "tombstone" line.
// - Rebroadcast fsyncs a "retry" line with the bumped counter.
//
// The file lives at <home>/<network>/mpool/pending.jsonl. It is chain-
// side of the secrets boundary (never in keystore/, secrets/, or
// backups/), but `lantern reset --chain-state` deliberately does NOT
// wipe it: user-signed pending messages are user state, not rebuildable
// chain state.
PersistPath string
// --- #123: alternate wire sink for devnet ---
//
// Sink, when non-nil, replaces the gossipsub topic.Publish call in
// Publish(). This is the devnet lotus-RPC path: on a single-node
// docker devnet the gossipsub mesh can't form, so signed messages
// are POST'd directly to the devnet lotus via Filecoin.MpoolPush
// instead. All other Pool semantics (persist journal, pending set,
// nonce derivation, reconcile/retry loop) work identically.
//
// When Sink is set, New() may be called with a nil pubsub instance;
// no topic is joined and no subscription is created. The reconcile
// loop still runs, rebroadcasting via Sink until inclusion.
Sink func(ctx context.Context, sm *ltypes.SignedMessage, raw []byte) (cid.Cid, error)
}
Config configures a Pool.
type PersistEntry ¶
type PersistEntry struct {
CID cid.Cid
Raw []byte
PublishedAt int64
Retries int
FirstSeenWall time.Time
}
PersistEntry is one live pending message in the durable store. Retries and PublishedAt are updated in place on rebroadcast; the raw bytes and FirstSeenWall are captured once at publish and never mutated.
func (*PersistEntry) SignedMessage ¶
func (e *PersistEntry) SignedMessage() (*ltypes.SignedMessage, error)
SignedMessage decodes the raw bytes back into a live SignedMessage. Returns an error if the bytes are corrupt (shouldn't happen for entries we wrote ourselves, but be defensive on load).
type Pool ¶
type Pool struct {
// contains filtered or unexported fields
}
Pool is a libp2p-gossipsub-backed message pool.
func New ¶
New starts a Pool: joins the topic, subscribes, and (if OnMessage is set) dispatches incoming messages to the handler in a background goroutine.
When ps is nil, no gossipsub topic is joined and no subscription is created. In that mode cfg.Sink must be set (used for the devnet lotus-RPC send-path per #123). Persist + reconcile loop + pending set still work identically; the difference is only the wire transport used by Publish and Rebroadcast.
func (*Pool) Close ¶
Close stops the subscription and topic, and closes the persist journal (when open). Safe when the pool was constructed without a pubsub instance (devnet Sink mode); the nil topic/sub branches are skipped.
func (*Pool) Forget ¶
Forget drops a CID from the pending set (call after the message is confirmed on-chain).
func (*Pool) Pending ¶
func (p *Pool) Pending() []*ltypes.SignedMessage
Pending returns a snapshot of locally pushed message CIDs (and their signed-message bodies) still awaiting inclusion.
func (*Pool) Publish ¶
Publish validates `sm` superficially, marshals it, and publishes to the gossipsub topic. Returns the message CID and any error. In DryRun mode it returns the CID + ErrDryRun without publishing.
func (*Pool) Reconcile ¶
func (p *Pool) Reconcile(ctx context.Context, headEpoch int64, search SearchFunc)
Reconcile runs one pass of the confirm/retry state machine at the given chain head epoch. Intended to be called once per new head. It never holds the pool lock across the SearchFunc call or a rebroadcast.
type SearchFunc ¶
SearchFunc resolves whether a published message CID has landed on chain. The daemon wires this to ChainAPI.StateSearchMsg (already local + zero Glif). It must be safe to call without holding the pool lock.
type SearchResult ¶
type SearchResult int
SearchResult reports whether a message was found on chain.
const ( // SearchUnknown: not found (yet) — keep waiting / retry per policy. SearchUnknown SearchResult = iota // SearchFound: confirmed on chain — drop from pending. SearchFound )
type Stats ¶
type Stats struct {
Received uint64
Rejected uint64
Published uint64
Rebroadcasts uint64 // #47
Confirmed uint64 // #47
Failed uint64 // #47
PendingCnt int
Topic string
Restored uint64 // #119 — entries re-registered from persist journal on startup
PersistPath string // #119 — empty when persistence is disabled
}
Stats reports observable counters.