Skip to main content
import "github.com/populist/protocol/tx"

Tx

The canonical transaction envelope. All protocol transactions share this envelope; the Type field determines which Data payload struct to use.
type Tx struct {
    Type      uint8           // wire-format discriminator; see TxType* constants
    Signature []byte          // sender authentication
    Data      json.RawMessage // JSON payload
}

DecodeTx

func DecodeTx(txBytes []byte) (*Tx, error)
Decodes a JSON-encoded transaction. Returns an error if the bytes are not valid JSON or do not conform to the Tx envelope schema.

EncodeTx

func EncodeTx(tx *Tx) ([]byte, error)
Encodes a transaction to JSON bytes for broadcast over the canonical node.

Tx.Validate

func (tx *Tx) Validate() error
Performs stateless validation:
  • Type must be one of the five TxType* constants
  • Signature must be non-empty
  • Data must be non-empty and valid JSON for the given type
  • Type-specific required fields are checked (e.g., poll_id, ZK fields for ballots)
Stateful checks (duplicate vote, ZK proof validity, IDV signature) are in state.ValidateTx.

Tx.UnmarshalData

func (tx *Tx) UnmarshalData(v interface{}) error
Decodes tx.Data into the provided struct pointer. Use with the appropriate data type:
var data tx.BallotCastData
if err := transaction.UnmarshalData(&data); err != nil { ... }

Data types

BallotCastData

The most complex payload. It supports both the preferred non-ZK tier and the high-assurance ZK tier.
type BallotCastData struct {
    PollID             string
    ZKNullifier        string   // optional in ZK tier: MiMC(person_secret, poll_id)
    ZKNullifierProof   []byte   // optional in ZK tier: Groth16 proof bytes
    ZKCommitment       string   // optional in ZK tier: MiMC(person_secret)
    DiditCommitmentSig []byte   // optional in ZK tier: sig over sha256(commitment ‖ poll_id)
    VoterPubKey        string   // required in preferred non-ZK tier; still present in current ZK flow
    VoterSig           []byte   // required in preferred non-ZK tier; still present in current ZK flow
    DiditDeviceSig     []byte   // required in preferred non-ZK tier
    Choices            []string // vote direction(s)
    BallotNonce        string   // random; ballot_id = H(BallotNonce)
    Timestamp          int64
}
In the preferred non-ZK tier, the runtime derives identity_hash from SHA-256(voter_pub_key ‖ poll_id) after validating voter_sig and didit_device_sig. In the ZK tier, the runtime uses zk_nullifier and zk_nullifier_proof. Which fields are required depends on whether a ZK verifier is loaded at startup.

PollCreateData

type PollCreateData struct {
    PollID       string
    Question     string
    Options      []string  // minimum 2
    VotingMethod string    // defaults to "plurality"
    StartTime    int64
    EndTime      int64
}

ConfirmReceiptData

type ConfirmReceiptData struct {
    PollID       string
    IdentityHash string  // ZK nullifier = MiMC(person_secret, poll_id)
}

ValidatorRegistrationData

type ValidatorRegistrationData struct {
    PubKeyBase64 string  // 32-byte Ed25519 key, base64-encoded
    Power        int64   // >0 to add; 0 to remove from active set
    Name         string
}