testutil

package
v0.5.38 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 29, 2026 License: MIT Imports: 40 Imported by: 0

Documentation

Overview

Package testutil provides shared test infrastructure for the Shielded-Vote chain integration tests. It includes reusable message constructors, raw tx encoding helpers, and a TestApp that wraps SvoteApp for in-process ABCI testing.

Index

Constants

View Source
const TestAuthority = "sv1authority"

TestAuthority is the module authority address used by all keeper tests.

Variables

View Source
var DefaultVoteManagerAddress = TestAccAddr(99)

DefaultVoteManagerAddress is the canonical test vote-manager address used in fixtures and integration helpers (valid bech32, seed 99). Not to be confused with x/vote/module.go's DefaultVoteManagerAddresses, which is the production default-genesis list.

View Source
var DummyPallasPoint = elgamal.PallasGenerator().ToAffineCompressed()

DummyPallasPoint is a valid compressed Pallas curve point (the generator) for use as a dummy rk / RVpk in test messages. Must be on-curve and non-identity to pass UnmarshalPublicKey validation in the ante handler.

Functions

func ActiveRoundFixture

func ActiveRoundFixture(roundID []byte) *types.VoteRound

ActiveRoundFixture returns a VoteRound in ACTIVE status with sensible defaults. Used to seed keeper state directly in unit tests without going through CreateVotingSession.

func DefaultOptions

func DefaultOptions() []*types.VoteOption

DefaultOptions returns the standard binary vote options (Support/Oppose).

func ExpiredCreateVotingSessionAt

func ExpiredCreateVotingSessionAt(refTime time.Time) *types.MsgCreateVotingSession

ExpiredCreateVotingSessionAt returns a MsgCreateVotingSession with VoteEndTime in the past relative to the given reference time.

func FpLE

func FpLE(v uint64) []byte

FpLE returns a 32-byte little-endian encoding of v as a Pallas Fp element. Values 0 <= v < 2^64 are always canonical. Use for commitment tree leaves in tests.

func MakeNullifier

func MakeNullifier(seed byte) []byte

MakeNullifier creates a deterministic 32-byte nullifier from a seed byte.

func MustEncodeAckCeremonyTx

func MustEncodeAckCeremonyTx(msg proto.Message) []byte

MustEncodeAckCeremonyTx encodes a MsgAckExecutiveAuthorityKey into the raw wire format [tag || protobuf_msg]. Only MsgAck uses the custom wire format; all other ceremony messages use standard Cosmos SDK transactions. Panics on encoding failure (safe for tests).

func MustEncodeVoteTx

func MustEncodeVoteTx(msg types.VoteMessage) []byte

MustEncodeVoteTx encodes a VoteMessage into the raw wire format [tag || protobuf_msg] used by the custom ABCI pipeline. Panics on encoding failure (safe for tests).

func SampleProposals

func SampleProposals() []*types.Proposal

SampleProposals returns two sample proposals for test fixtures. Proposal IDs must be 1-indexed per ValidateBasic (expected 1, 2, ...).

func ShuffleWithSeed

func ShuffleWithSeed[T any](in []T, seed uint64) []T

ShuffleWithSeed returns a deterministically shuffled copy of in.

func TestAccAddr

func TestAccAddr(seed byte) string

TestAccAddr generates a deterministic valid bech32 account address from a seed byte.

func TestValAddr

func TestValAddr(seed byte) string

TestValAddr generates a deterministic valid bech32 validator operator address from a seed byte.

func ValidCastVote

func ValidCastVote(roundID []byte, anchorHeight uint64, nullifierSeed byte) *types.MsgCastVote

ValidCastVote returns a MsgCastVote with mock data. VoteAuthorityNoteNew and VoteCommitment use canonical Fp encodings for the commitment tree. RVpkX and RVpkY are 32-byte stubs for condition 4 (Spend Authority). Sighash is computed on-chain by the ante handler from the message fields.

func ValidCastVoteN

func ValidCastVoteN(roundID []byte, anchorHeight uint64, n int, seed uint64) []*types.MsgCastVote

ValidCastVoteN returns n deterministic MsgCastVote messages with unique VAN nullifiers and commitment leaves. The seed controls reproducible generation.

func ValidCreateVotingSession

func ValidCreateVotingSession() *types.MsgCreateVotingSession

ValidCreateVotingSession returns a MsgCreateVotingSession with all fields populated. The VoteEndTime is set 1 hour in the future from the reference time.

func ValidCreateVotingSessionAt

func ValidCreateVotingSessionAt(refTime time.Time) *types.MsgCreateVotingSession

ValidCreateVotingSessionAt returns a MsgCreateVotingSession with VoteEndTime set relative to the given reference time. Use this when the block time is deterministic.

func ValidCreateVotingSessionWithEndTime

func ValidCreateVotingSessionWithEndTime(endTime time.Time) *types.MsgCreateVotingSession

ValidCreateVotingSessionWithEndTime returns a MsgCreateVotingSession with an explicit VoteEndTime. Use when you need a specific end time (e.g. 10 seconds from block time).

func ValidDelegation

func ValidDelegation(roundID []byte, nullifierSeed byte) *types.MsgDelegateVote

ValidDelegation returns a MsgDelegateVote with mock proof data. Each call returns unique gov nullifiers derived from the provided seed. CmxNew and VanCmx use canonical Fp encodings so the commitment tree FFI accepts them. Sighash is set to a dummy 32-byte value; chain only checks length + signature.

func ValidDelegationN

func ValidDelegationN(roundID []byte, n int, seed uint64) []*types.MsgDelegateVote

ValidDelegationN returns n deterministic MsgDelegateVote messages with unique gov nullifiers and VAN commitments. The seed controls reproducible generation.

func ValidRevealShare

func ValidRevealShare(roundID []byte, anchorHeight uint64, nullifierSeed byte) *types.MsgRevealShare

ValidRevealShare returns a MsgRevealShare with mock data. EncShare is a valid ElGamal identity ciphertext (two identity Pallas points) that passes keeper validation. The nullifierSeed only affects ShareNullifier.

func ValidRevealShareReal

func ValidRevealShareReal(roundID []byte, anchorHeight uint64, nullifierSeed byte,
	proposalID uint32, decision uint32, encShare []byte,
) *types.MsgRevealShare

ValidRevealShareReal returns a MsgRevealShare with a real ElGamal ciphertext as the EncShare. Use this when testing end-to-end encryption/decryption.

func ValidSubmitTally

func ValidSubmitTally(roundID []byte, creator string) *types.MsgSubmitTally

ValidSubmitTally returns a MsgSubmitTally for the given round ID and creator. By default it includes a single entry matching the default ValidRevealShare fixture (proposal_id=1, vote_decision=1, total_value=1000).

func ValidSubmitTallyWithEntries

func ValidSubmitTallyWithEntries(roundID []byte, creator string, entries []*types.TallyEntry) *types.MsgSubmitTally

ValidSubmitTallyWithEntries returns a MsgSubmitTally with custom entries.

Types

type NullifierConflictSet

type NullifierConflictSet struct {
	GovWinner *types.MsgDelegateVote
	GovLoser  *types.MsgDelegateVote
	GovFresh  *types.MsgDelegateVote

	VanWinner *types.MsgCastVote
	VanLoser  *types.MsgCastVote
	VanFresh  *types.MsgCastVote
}

NullifierConflictSet contains conflicting/fresh tx fixtures for both delegation (gov nullifiers) and cast-vote (VAN nullifiers) race tests.

func BuildConflictingNullifierSet

func BuildConflictingNullifierSet(roundID []byte, anchorHeight uint64, seed uint64) NullifierConflictSet

BuildConflictingNullifierSet builds deterministic tx fixtures where two txs intentionally conflict on the same nullifier and one tx is fresh.

type TestApp

type TestApp struct {
	*app.SvoteApp

	Height int64
	Time   time.Time

	// ProposerAddress is the consensus address of the genesis validator,
	// passed in every FinalizeBlock request so the ante handler can verify
	// that MsgSubmitTally creators match the block proposer.
	ProposerAddress []byte

	// ValPrivKey is the secp256k1 private key of the genesis validator's
	// operator account. Used for signing ceremony messages in tests.
	ValPrivKey *secp256k1.PrivKey

	// EaSkDir is the directory for per-round ea_sk files, derived from
	// the "vote.ea_sk_path" app option. Empty when no EA key is configured.
	EaSkDir string

	// EaPk is the EA public key (compressed Pallas point). When set, SeedVotingSession
	// uses this instead of a zero placeholder.
	EaPk []byte
	// contains filtered or unexported fields
}

TestApp wraps SvoteApp with helpers for driving the ABCI lifecycle in integration tests. No CometBFT process or network is involved — tests call FinalizeBlock/Commit/CheckTx directly.

func SetupTestApp

func SetupTestApp(t *testing.T) *TestApp

SetupTestApp creates a fresh SvoteApp backed by an in-memory database, initializes the chain with a proper genesis (including a genesis validator), and returns a TestApp ready for integration testing.

func SetupTestAppWithEAKey

func SetupTestAppWithEAKey(t *testing.T) (*TestApp, *elgamal.PublicKey, []byte)

SetupTestAppWithEAKey creates a TestApp with a real ElGamal keypair for the EA (Election Authority). The secret key is written to a temp file and passed via the "vote.ea_sk_path" app option so that PrepareProposal can decrypt tallies. Returns both the TestApp and the public key for encrypting shares.

func SetupTestAppWithPallasKey

func SetupTestAppWithPallasKey(t *testing.T) (ta *TestApp, pallasSk *elgamal.SecretKey, pallasPk *elgamal.PublicKey, eaSk *elgamal.SecretKey, eaPk *elgamal.PublicKey)

SetupTestAppWithPallasKey creates a TestApp with both an EA keypair and a Pallas keypair written to temp files and passed via app options. This enables testing the auto-ack PrepareProposal handler. Returns the TestApp, the validator's Pallas secret key, the EA secret key, and the EA public key.

func (*TestApp) CallPrepareProposal

func (ta *TestApp) CallPrepareProposal() *abci.ResponsePrepareProposal

CallPrepareProposal builds a RequestPrepareProposal for the next block (current height+1, time+5s) and calls PrepareProposal on the app. Returns the response containing any auto-injected txs.

func (*TestApp) CallPrepareProposalWithTxs

func (ta *TestApp) CallPrepareProposalWithTxs(txs [][]byte) *abci.ResponsePrepareProposal

CallPrepareProposalWithTxs builds a RequestPrepareProposal for the next block with the given mempool txs and calls PrepareProposal. Returns the response.

func (*TestApp) CallProcessProposal

func (ta *TestApp) CallProcessProposal(txs [][]byte) *abci.ResponseProcessProposal

CallProcessProposal calls ProcessProposal with the given txs at the next block height (current height+1, time+5s). Returns the response.

func (*TestApp) CheckTxSync

func (ta *TestApp) CheckTxSync(txBytes []byte) *abci.ResponseCheckTx

CheckTxSync runs CheckTx (type New) on raw tx bytes and returns the response.

func (*TestApp) DeliverVoteTx

func (ta *TestApp) DeliverVoteTx(txBytes []byte) *abci.ExecTxResult

DeliverVoteTx submits a single raw vote tx through FinalizeBlock + Commit and returns the ExecTxResult. The block height and time are advanced.

func (*TestApp) DeliverVoteTxs

func (ta *TestApp) DeliverVoteTxs(txs [][]byte) []*abci.ExecTxResult

DeliverVoteTxs submits multiple raw vote txs in a single block through FinalizeBlock + Commit and returns all ExecTxResults.

func (*TestApp) MustBuildSignedCeremonyTx

func (ta *TestApp) MustBuildSignedCeremonyTx(msg sdk.Msg) []byte

MustBuildSignedCeremonyTx builds a standard Cosmos SDK transaction containing the ceremony message, signs it with the genesis validator's secp256k1 key, and returns the encoded tx bytes. Panics on failure (safe for tests).

func (*TestApp) MustGetVoteRound added in v0.4.0

func (ta *TestApp) MustGetVoteRound(roundID []byte) *types.VoteRound

MustGetVoteRound reads the round from committed state, failing the test on error.

func (*TestApp) NextBlock

func (ta *TestApp) NextBlock()

NextBlock commits an empty block, advancing height and time by 5 seconds. Triggers EndBlocker (commitment tree root computation).

func (*TestApp) NextBlockAtTime

func (ta *TestApp) NextBlockAtTime(t time.Time)

NextBlockAtTime commits an empty block at a specific time, advancing height by 1. Triggers EndBlocker (commitment tree root computation, round status transitions).

func (*TestApp) NextBlockWithPrepareProposal

func (ta *TestApp) NextBlockWithPrepareProposal()

NextBlockWithPrepareProposal calls PrepareProposal to collect any auto-injected txs, then feeds them into FinalizeBlock + Commit. This simulates a real block production cycle where PrepareProposal injects tally txs.

func (*TestApp) NextBlockWithTxs added in v0.4.0

func (ta *TestApp) NextBlockWithTxs(txs [][]byte)

NextBlockWithTxs advances the block by 5 s and runs FinalizeBlock + Commit with the given pre-built txs. Use this when you need to deliver specific txs (e.g. from a directly-invoked handler) without going through PrepareProposal.

func (*TestApp) RecheckTxSync

func (ta *TestApp) RecheckTxSync(txBytes []byte) *abci.ResponseCheckTx

RecheckTxSync runs CheckTx (type Recheck) on raw tx bytes and returns the response.

func (*TestApp) RegisterPallasKey added in v0.4.0

func (ta *TestApp) RegisterPallasKey(pallasPk *elgamal.PublicKey)

RegisterPallasKey registers the given Pallas public key for the genesis validator via a signed MsgRegisterPallasKey delivered through FinalizeBlock.

func (*TestApp) SeedConfirmedCeremony

func (ta *TestApp) SeedConfirmedCeremony(_ []byte)

SeedConfirmedCeremony is a no-op retained for test compatibility. Ceremony state is now embedded per-round; rounds start PENDING and auto-confirm via deal/ack. Tests that need an ACTIVE round with ea_pk should use SeedVotingSession directly (which sets ea_pk on the round).

func (*TestApp) SeedDealtCeremony

func (ta *TestApp) SeedDealtCeremony(pallasPkBytes, eaPkBytes []byte, validators []*types.ValidatorPallasKey) []byte

SeedDealtCeremony creates a PENDING round with DEALT ceremony fields. The round includes the given validators. A default threshold and placeholder Feldman commitments are set. Commits via an empty block. Returns the round ID.

func (*TestApp) SeedDealtCeremonyThreshold

func (ta *TestApp) SeedDealtCeremonyThreshold(
	eaPkBytes []byte,
	validators []*types.ValidatorPallasKey,
	threshold uint32,
	feldmanCommitments [][]byte,
) []byte

SeedDealtCeremonyThreshold creates a PENDING round with DEALT ceremony fields. Callers supply pre-computed ECIES payloads, Feldman commitments, and the threshold t. This lets ack handler tests exercise Feldman verification without going through the full DKG flow.

func (*TestApp) SeedRegisteringCeremony

func (ta *TestApp) SeedRegisteringCeremony(validators []*types.ValidatorPallasKey) []byte

SeedRegisteringCeremony creates a PENDING round with REGISTERING ceremony status and the given validators. Commits via an empty block. Returns the round ID. Used for testing auto-deal and full ceremony cycle flows.

func (*TestApp) SeedTallyingRoundThreshold

func (ta *TestApp) SeedTallyingRoundThreshold(
	roundID []byte,
	threshold uint32,
	proposals []*types.Proposal,
	validators []*types.ValidatorPallasKey,
	feldmanCommitments [][]byte,
) []byte

SeedTallyingRoundThreshold creates a TALLYING round in threshold mode directly in the KV store and commits via an empty block. Returns the round ID. Callers can subsequently use VoteKeeper().AddToTally to populate ciphertext accumulators, then call WriteShareForRound to put the share on disk before calling CallPrepareProposal.

If any validator has ShamirIndex == 0 (unset), this function assigns ShamirIndex = position+1, mirroring what CreateVotingSession does in production so that Lagrange interpolation uses the correct x-coordinates.

func (*TestApp) SeedVoteManagers added in v0.5.8

func (ta *TestApp) SeedVoteManagers(addrs ...string)

SeedVoteManagers writes the vote-manager set directly into the module's KV store and commits via an empty block. Must be called before any CreateVotingSession, since the handler requires the creator to be in the set.

func (*TestApp) SeedVotingSession

func (ta *TestApp) SeedVotingSession(msg *types.MsgCreateVotingSession) []byte

SeedVotingSession creates a VoteRound directly in the KV store from a MsgCreateVotingSession, bypassing the ABCI pipeline. The round is committed via an empty block. Returns the derived vote_round_id.

MsgCreateVotingSession is a standard Cosmos SDK tx (signed by a vote manager), so it can't be submitted via the custom vote tx wire format. For integration tests that need an active round to exercise other vote messages (delegation, cast, reveal, tally), this helper seeds the round directly — the session creation itself is not under test here.

func (*TestApp) ValidatorAccAddr

func (ta *TestApp) ValidatorAccAddr() string

ValidatorAccAddr returns the account (bech32 acc) address of the genesis validator's operator key. Same raw bytes as ValidatorOperAddr but encoded with the account prefix. Use this as the Creator field in ceremony messages that are handled by RegisterPallasKey and similar handlers which derive the valoper address internally from the account address.

func (*TestApp) ValidatorOperAddr

func (ta *TestApp) ValidatorOperAddr() string

ValidatorOperAddr returns the operator (valoper) address of the genesis validator. This queries the staking keeper for all validators and returns the first one's operator address.

func (*TestApp) VoteKeeper

func (ta *TestApp) VoteKeeper() *votekeeper.Keeper

VoteKeeper returns the vote module keeper for querying state in tests.

func (*TestApp) WriteEaSkForRound

func (ta *TestApp) WriteEaSkForRound(roundID []byte, eaSkBytes []byte)

WriteEaSkForRound writes the ea_sk bytes to the per-round file path so the tally PrepareProposal handler can load it. Call after creating a round.

func (*TestApp) WriteShareForRound

func (ta *TestApp) WriteShareForRound(roundID []byte, shareBytes []byte)

WriteShareForRound writes a raw 32-byte Shamir share scalar to <EaSkDir>/share.<hex(round_id)>, the path the partial decrypt injector expects. Call after creating a TALLYING round in threshold mode.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL