model

package
v0.38.0-preview.0.0.8 Latest Latest
Warning

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

Go to latest
Published: Nov 27, 2024 License: AGPL-3.0 Imports: 8 Imported by: 39

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrUnverifiableBlock = errors.New("block proposal can't be verified, because its view is above the finalized view, but its QC is below the finalized view")
	ErrInvalidSignature  = errors.New("invalid signature")
	// ErrViewForUnknownEpoch is returned when Epoch information is queried for a view that is
	// outside of all cached epochs. This can happen when a query is made for a view in the
	// next epoch, if that epoch is not committed yet. This can also happen when an
	// old epoch is queried (>3 in the past), even if that epoch does exist in storage.
	ErrViewForUnknownEpoch = fmt.Errorf("by-view query for unknown epoch")
)

Functions

func BeaconSignature added in v0.32.0

func BeaconSignature(qc *flow.QuorumCertificate) ([]byte, error)

BeaconSignature extracts the source of randomness from the QC sigData.

The sigData is an RLP encoded structure that is part of QuorumCertificate. The function only ever returns a model.InvalidFormatError, which indicates an invalid encoding.

func IsByzantineThresholdExceededError added in v0.29.0

func IsByzantineThresholdExceededError(err error) bool

func IsConfigurationError added in v0.23.9

func IsConfigurationError(err error) bool

IsConfigurationError returns whether err is a ConfigurationError

func IsDoubleTimeoutError added in v0.29.0

func IsDoubleTimeoutError(err error) bool

IsDoubleTimeoutError returns whether an error is DoubleTimeoutError

func IsDoubleVoteError added in v0.23.9

func IsDoubleVoteError(err error) bool

IsDoubleVoteError returns whether an error is DoubleVoteError

func IsDuplicatedSignerError added in v0.23.9

func IsDuplicatedSignerError(err error) bool

IsDuplicatedSignerError returns whether err is an DuplicatedSignerError

func IsInsufficientSignaturesError added in v0.23.9

func IsInsufficientSignaturesError(err error) bool

IsInsufficientSignaturesError returns whether err is an InsufficientSignaturesError

func IsInvalidAggregatedKeyError added in v0.30.0

func IsInvalidAggregatedKeyError(err error) bool

IsInvalidAggregatedKeyError returns whether err is an InvalidAggregatedKeyError

func IsInvalidBlockError

func IsInvalidBlockError(err error) bool

IsInvalidBlockError returns whether an error is InvalidBlockError

func IsInvalidFormatError added in v0.26.1

func IsInvalidFormatError(err error) bool

IsInvalidFormatError returns whether err is a InvalidFormatError

func IsInvalidProposalError added in v0.31.0

func IsInvalidProposalError(err error) bool

IsInvalidProposalError returns whether an error is InvalidProposalError

func IsInvalidQCError added in v0.29.0

func IsInvalidQCError(err error) bool

IsInvalidQCError returns whether an error is InvalidQCError

func IsInvalidSignatureIncludedError added in v0.23.9

func IsInvalidSignatureIncludedError(err error) bool

IsInvalidSignatureIncludedError returns whether err is an InvalidSignatureIncludedError

func IsInvalidSignerError added in v0.23.9

func IsInvalidSignerError(err error) bool

IsInvalidSignerError returns whether err is an InvalidSignerError

func IsInvalidTCError added in v0.29.0

func IsInvalidTCError(err error) bool

IsInvalidTCError returns whether an error is InvalidQCError

func IsInvalidTimeoutError added in v0.29.0

func IsInvalidTimeoutError(err error) bool

IsInvalidTimeoutError returns whether an error is InvalidTimeoutError

func IsInvalidVoteError

func IsInvalidVoteError(err error) bool

IsInvalidVoteError returns whether an error is InvalidVoteError

func IsMissingBlockError

func IsMissingBlockError(err error) bool

IsMissingBlockError returns whether an error is MissingBlockError

func IsNoTimeoutError added in v0.29.0

func IsNoTimeoutError(err error) bool

IsNoTimeoutError returns whether an error is NoTimeoutError

func IsNoVoteError

func IsNoVoteError(err error) bool

IsNoVoteError returns whether an error is NoVoteError

func NewConfigurationError added in v0.23.9

func NewConfigurationError(err error) error

func NewConfigurationErrorf added in v0.23.9

func NewConfigurationErrorf(msg string, args ...interface{}) error

func NewDoubleTimeoutErrorf added in v0.29.0

func NewDoubleTimeoutErrorf(firstTimeout, conflictingTimeout *TimeoutObject, msg string, args ...interface{}) error

func NewDoubleVoteErrorf added in v0.23.9

func NewDoubleVoteErrorf(firstVote, conflictingVote *Vote, msg string, args ...interface{}) error

func NewDuplicatedSignerError added in v0.23.9

func NewDuplicatedSignerError(err error) error

func NewDuplicatedSignerErrorf added in v0.23.9

func NewDuplicatedSignerErrorf(msg string, args ...interface{}) error

func NewInsufficientSignaturesError added in v0.23.9

func NewInsufficientSignaturesError(err error) error

func NewInsufficientSignaturesErrorf added in v0.23.9

func NewInsufficientSignaturesErrorf(msg string, args ...interface{}) error

func NewInvalidAggregatedKeyError added in v0.30.0

func NewInvalidAggregatedKeyError(err error) error

func NewInvalidAggregatedKeyErrorf added in v0.30.0

func NewInvalidAggregatedKeyErrorf(msg string, args ...interface{}) error

func NewInvalidBlockErrorf added in v0.31.0

func NewInvalidBlockErrorf(block *Block, msg string, args ...interface{}) error

func NewInvalidFormatError added in v0.26.1

func NewInvalidFormatError(err error) error

func NewInvalidFormatErrorf added in v0.26.1

func NewInvalidFormatErrorf(msg string, args ...interface{}) error

func NewInvalidProposalErrorf added in v0.31.0

func NewInvalidProposalErrorf(proposal *SignedProposal, msg string, args ...interface{}) error

func NewInvalidSignatureIncludedError added in v0.23.9

func NewInvalidSignatureIncludedError(err error) error

func NewInvalidSignatureIncludedErrorf added in v0.23.9

func NewInvalidSignatureIncludedErrorf(msg string, args ...interface{}) error

func NewInvalidSignerError added in v0.23.9

func NewInvalidSignerError(err error) error

func NewInvalidSignerErrorf added in v0.23.9

func NewInvalidSignerErrorf(msg string, args ...interface{}) error

func NewInvalidTimeoutErrorf added in v0.29.0

func NewInvalidTimeoutErrorf(timeout *TimeoutObject, msg string, args ...interface{}) error

func NewInvalidVoteErrorf added in v0.23.9

func NewInvalidVoteErrorf(vote *Vote, msg string, args ...interface{}) error

func NewNoTimeoutErrorf added in v0.29.0

func NewNoTimeoutErrorf(msg string, args ...interface{}) error

func NewNoVoteErrorf added in v0.29.0

func NewNoVoteErrorf(msg string, args ...interface{}) error

Types

type Block

type Block struct {
	View        uint64
	BlockID     flow.Identifier
	ProposerID  flow.Identifier
	QC          *flow.QuorumCertificate
	PayloadHash flow.Identifier
	Timestamp   time.Time
}

Block is the HotStuff algorithm's concept of a block, which - in the bigger picture - corresponds to the block header.

func BlockFromFlow

func BlockFromFlow(header *flow.Header) *Block

BlockFromFlow converts a flow header to a hotstuff block.

func GenesisBlockFromFlow

func GenesisBlockFromFlow(header *flow.Header) *Block

GenesisBlockFromFlow returns a HotStuff block model representing a genesis block based on the given header.

type ByzantineThresholdExceededError

type ByzantineThresholdExceededError struct {
	Evidence string
}

ByzantineThresholdExceededError is raised if HotStuff detects malicious conditions, which prove that the Byzantine threshold of consensus replicas has been exceeded. Per definition, this is the case when there are byzantine consensus replicas with ≥ 1/3 of the committee's total weight. In this scenario, foundational consensus safety guarantees fail. Generally, the protocol cannot continue in such conditions. We represent this exception as with a dedicated type, so its occurrence can be detected by higher-level logic and escalated to the node operator.

func (ByzantineThresholdExceededError) Error

type CertifiedBlock added in v0.30.2

type CertifiedBlock struct {
	Block        *Block
	CertifyingQC *flow.QuorumCertificate
}

CertifiedBlock holds a certified block, which is a block and a QC that is pointing to the block. A QC is the aggregated form of votes from a supermajority of HotStuff and therefore proves validity of the block. A certified block satisfies: Block.View == QC.View and Block.BlockID == QC.BlockID

func NewCertifiedBlock added in v0.30.2

func NewCertifiedBlock(block *Block, qc *flow.QuorumCertificate) (CertifiedBlock, error)

NewCertifiedBlock constructs a new certified block. It checks the consistency requirements and returns an exception otherwise:

Block.View == QC.View and Block.BlockID == QC.BlockID

func (*CertifiedBlock) ID added in v0.30.2

func (b *CertifiedBlock) ID() flow.Identifier

ID returns unique identifier for the block. To avoid repeated computation, we use value from the QC.

func (*CertifiedBlock) View added in v0.30.2

func (b *CertifiedBlock) View() uint64

View returns view where the block was proposed.

type ConfigurationError

type ConfigurationError struct {
	// contains filtered or unexported fields
}

ConfigurationError indicates that a constructor or component was initialized with invalid or inconsistent parameters.

func (ConfigurationError) Error

func (e ConfigurationError) Error() string

func (ConfigurationError) Unwrap added in v0.23.9

func (e ConfigurationError) Unwrap() error

type DoubleTimeoutError added in v0.29.0

type DoubleTimeoutError struct {
	FirstTimeout       *TimeoutObject
	ConflictingTimeout *TimeoutObject
	// contains filtered or unexported fields
}

DoubleTimeoutError indicates that a consensus replica has created two different timeout objects for same view.

func AsDoubleTimeoutError added in v0.29.0

func AsDoubleTimeoutError(err error) (*DoubleTimeoutError, bool)

AsDoubleTimeoutError determines whether the given error is a DoubleTimeoutError (potentially wrapped). It follows the same semantics as a checked type cast.

func (DoubleTimeoutError) Error added in v0.29.0

func (e DoubleTimeoutError) Error() string

func (DoubleTimeoutError) Unwrap added in v0.29.0

func (e DoubleTimeoutError) Unwrap() error

type DoubleVoteError added in v0.23.9

type DoubleVoteError struct {
	FirstVote       *Vote
	ConflictingVote *Vote
	// contains filtered or unexported fields
}

DoubleVoteError indicates that a consensus replica has voted for two different blocks, or has provided two semantically different votes for the same block.

func AsDoubleVoteError added in v0.23.9

func AsDoubleVoteError(err error) (*DoubleVoteError, bool)

AsDoubleVoteError determines whether the given error is a DoubleVoteError (potentially wrapped). It follows the same semantics as a checked type cast.

func (DoubleVoteError) Error added in v0.23.9

func (e DoubleVoteError) Error() string

func (DoubleVoteError) Unwrap added in v0.23.9

func (e DoubleVoteError) Unwrap() error

type DuplicatedSignerError added in v0.23.9

type DuplicatedSignerError struct {
	// contains filtered or unexported fields
}

DuplicatedSignerError indicates that a signature from the same node ID has already been added

func (DuplicatedSignerError) Error added in v0.23.9

func (e DuplicatedSignerError) Error() string

func (DuplicatedSignerError) Unwrap added in v0.23.9

func (e DuplicatedSignerError) Unwrap() error

type InsufficientSignaturesError added in v0.23.9

type InsufficientSignaturesError struct {
	// contains filtered or unexported fields
}

InsufficientSignaturesError indicates that not enough signatures have been stored to complete the operation.

func (InsufficientSignaturesError) Error added in v0.23.9

func (InsufficientSignaturesError) Unwrap added in v0.23.9

type InvalidAggregatedKeyError added in v0.30.0

type InvalidAggregatedKeyError struct {
	// contains filtered or unexported fields
}

InvalidAggregatedKeyError indicates that the aggregated key is invalid which makes any aggregated signature invalid.

func (InvalidAggregatedKeyError) Unwrap added in v0.30.0

func (e InvalidAggregatedKeyError) Unwrap() error

type InvalidBlockError

type InvalidBlockError struct {
	InvalidBlock *Block
	Err          error
}

InvalidBlockError indicates that the block is invalid

func AsInvalidBlockError added in v0.31.0

func AsInvalidBlockError(err error) (*InvalidBlockError, bool)

AsInvalidBlockError determines whether the given error is a InvalidProposalError (potentially wrapped). It follows the same semantics as a checked type cast.

func (InvalidBlockError) Error

func (e InvalidBlockError) Error() string

func (InvalidBlockError) Unwrap

func (e InvalidBlockError) Unwrap() error

type InvalidFormatError added in v0.26.1

type InvalidFormatError struct {
	// contains filtered or unexported fields
}

InvalidFormatError indicates that some data has an incompatible format.

func (InvalidFormatError) Error added in v0.26.1

func (e InvalidFormatError) Error() string

func (InvalidFormatError) Unwrap added in v0.26.1

func (e InvalidFormatError) Unwrap() error

type InvalidProposalError added in v0.31.0

type InvalidProposalError struct {
	InvalidProposal *SignedProposal
	Err             error
}

InvalidProposalError indicates that the proposal is invalid

func AsInvalidProposalError added in v0.31.0

func AsInvalidProposalError(err error) (*InvalidProposalError, bool)

AsInvalidProposalError determines whether the given error is a InvalidProposalError (potentially wrapped). It follows the same semantics as a checked type cast.

func (InvalidProposalError) Error added in v0.31.0

func (e InvalidProposalError) Error() string

func (InvalidProposalError) Unwrap added in v0.31.0

func (e InvalidProposalError) Unwrap() error

type InvalidQCError added in v0.29.0

type InvalidQCError struct {
	BlockID flow.Identifier
	View    uint64
	Err     error
}

InvalidQCError indicates that the QC for block identified by `BlockID` and `View` is invalid

func (InvalidQCError) Error added in v0.29.0

func (e InvalidQCError) Error() string

func (InvalidQCError) Unwrap added in v0.29.0

func (e InvalidQCError) Unwrap() error

type InvalidSignatureIncludedError added in v0.23.9

type InvalidSignatureIncludedError struct {
	// contains filtered or unexported fields
}

InvalidSignatureIncludedError indicates that some signatures, included via TrustedAdd, are invalid

func (InvalidSignatureIncludedError) Error added in v0.23.9

func (InvalidSignatureIncludedError) Unwrap added in v0.23.9

type InvalidSignerError added in v0.23.9

type InvalidSignerError struct {
	// contains filtered or unexported fields
}

InvalidSignerError indicates that the signer is not authorized or unknown

func (InvalidSignerError) Error added in v0.23.9

func (e InvalidSignerError) Error() string

func (InvalidSignerError) Unwrap added in v0.23.9

func (e InvalidSignerError) Unwrap() error

type InvalidTCError added in v0.29.0

type InvalidTCError struct {
	View uint64
	Err  error
}

InvalidTCError indicates that the TC for view identified by `View` is invalid

func (InvalidTCError) Error added in v0.29.0

func (e InvalidTCError) Error() string

func (InvalidTCError) Unwrap added in v0.29.0

func (e InvalidTCError) Unwrap() error

type InvalidTimeoutError added in v0.29.0

type InvalidTimeoutError struct {
	Timeout *TimeoutObject
	Err     error
}

InvalidTimeoutError indicates that the embedded timeout object is invalid

func AsInvalidTimeoutError added in v0.29.6

func AsInvalidTimeoutError(err error) (*InvalidTimeoutError, bool)

AsInvalidTimeoutError determines whether the given error is a InvalidTimeoutError (potentially wrapped). It follows the same semantics as a checked type cast.

func (InvalidTimeoutError) Error added in v0.29.0

func (e InvalidTimeoutError) Error() string

func (InvalidTimeoutError) Unwrap added in v0.29.0

func (e InvalidTimeoutError) Unwrap() error

type InvalidVoteError

type InvalidVoteError struct {
	Vote *Vote
	Err  error
}

InvalidVoteError indicates that the vote with identifier `VoteID` is invalid

func AsInvalidVoteError added in v0.29.6

func AsInvalidVoteError(err error) (*InvalidVoteError, bool)

AsInvalidVoteError determines whether the given error is a InvalidVoteError (potentially wrapped). It follows the same semantics as a checked type cast.

func (InvalidVoteError) Error

func (e InvalidVoteError) Error() string

func (InvalidVoteError) Unwrap

func (e InvalidVoteError) Unwrap() error

type MissingBlockError

type MissingBlockError struct {
	View    uint64
	BlockID flow.Identifier
}

MissingBlockError indicates that no block with identifier `BlockID` is known

func (MissingBlockError) Error

func (e MissingBlockError) Error() string

type NewViewEvent

type NewViewEvent TimerInfo

NewViewEvent indicates that a new view has started. While it has the same data model as `TimerInfo`, their semantics are different (hence we use different types): `TimerInfo` represents a continuous time interval. In contrast, NewViewEvent marks the specific point in time, when the timer is started.

type NoTimeoutError added in v0.29.0

type NoTimeoutError struct {
	Err error
}

NoTimeoutError contains the reason why hotstuff.SafetyRules refused to generate a `TimeoutObject` [TO] for the current view.

func (NoTimeoutError) Error added in v0.29.0

func (e NoTimeoutError) Error() string

func (NoTimeoutError) Unwrap added in v0.29.0

func (e NoTimeoutError) Unwrap() error

type NoVoteError

type NoVoteError struct {
	Err error
}

NoVoteError contains the reason why hotstuff.SafetyRules refused to generate a `Vote` for the current view.

func (NoVoteError) Error

func (e NoVoteError) Error() string

func (NoVoteError) Unwrap added in v0.29.0

func (e NoVoteError) Unwrap() error

type Proposal

type Proposal struct {
	Block      *Block
	LastViewTC *flow.TimeoutCertificate
}

Proposal represents a block proposal under construction. In order to decide whether a proposal is safe to sign, HotStuff's Safety Rules require proof that the leader entered the respective view in a protocol-compliant manner. Specifically, we require a TimeoutCertificate [TC] if and only if the QC in the block is _not_ for the immediately preceding view. Thereby we protect the consensus process from malicious leaders attempting to skip views that haven't concluded yet (a form of front-running attack). However, LastViewTC is only relevant until a QC is known that certifies the correctness of the block. Thereafter, the QC attests that honest consensus participants have confirmed the validity of the fork up to the latest certified block (including protocol-compliant view transitions).

By explicitly differentiating the Proposal from the SignedProposal (extending Proposal by adding the proposer's signature), we can unify the algorithmic path of signing block proposals. This codifies the important aspect that a proposer's signature for their own block is conceptually also just a vote (we explicitly use that for aggregating votes, including the proposer's own vote to a QC). In order to express this conceptual equivalence in code, the voting logic in Safety Rules must also operate on an unsigned Proposal.

TODO: atm, the flow.Header embeds the LastViewTC. However, for HotStuff we have `model.Block` and `model.Proposal`, where the latter was introduced when we added the PaceMaker to vanilla HotStuff. It would be more consistent, if we added `LastViewTC` to `model.Block`, or even better, introduce an interface for HotStuff's notion of a block (exposing the fields in `model.Block` plus LastViewTC)

func ProposalFromFlow

func ProposalFromFlow(header *flow.Header) *Proposal

ProposalFromFlow turns an unsigned flow header into a unsigned hotstuff block type.

type SigDataPacker added in v0.26.1

type SigDataPacker struct {
	// contains filtered or unexported fields
}

SigDataPacker implements logic for encoding/decoding SignatureData using RLP encoding.

func (*SigDataPacker) Decode added in v0.26.1

func (p *SigDataPacker) Decode(data []byte) (*SignatureData, error)

Decode performs decoding of SignatureData This function is side-effect free. It only ever returns a model.InvalidFormatError, which indicates an invalid encoding.

func (*SigDataPacker) Encode added in v0.26.1

func (p *SigDataPacker) Encode(sigData *SignatureData) ([]byte, error)

Encode performs encoding of SignatureData

type SignatureData added in v0.26.1

type SignatureData struct {
	// bit-vector indicating type of signature for each signer.
	// the order of each sig type matches the order of corresponding signer IDs
	SigType []byte

	AggregatedStakingSig         []byte
	AggregatedRandomBeaconSig    []byte
	ReconstructedRandomBeaconSig crypto.Signature
}

SignatureData is a compact data type for encoding the block signature data

type SignedProposal

type SignedProposal struct {
	Proposal
	SigData []byte
}

SignedProposal represent a new proposed block within HotStuff (and thus a header in the bigger picture), signed by the proposer.

CAUTION: the signature only covers the pair (Block.View, Block.BlockID). Therefore, only the data that is hashed into the BlockID is cryptographically secured by the proposer's signature. Specifically, the proposer's signature cannot be covered by the Block.BlockID, as the proposer _signs_ the Block.BlockID (otherwise we have a cyclic dependency).

func SignedProposalFromFlow

func SignedProposalFromFlow(header *flow.Header) *SignedProposal

SignedProposalFromFlow turns a flow header into a hotstuff block type.

func (*SignedProposal) ProposerVote

func (p *SignedProposal) ProposerVote() *Vote

ProposerVote extracts the proposer vote from the proposal

type TimeoutObject added in v0.29.0

type TimeoutObject struct {
	// View is the view number which is replica is timing out
	View uint64
	// NewestQC is the newest QC (by view) known to the creator of this TimeoutObject
	NewestQC *flow.QuorumCertificate
	// LastViewTC is the timeout certificate for previous view if NewestQC.View != View - 1, else nil
	LastViewTC *flow.TimeoutCertificate
	// SignerID is the identifier of replica that has signed this TimeoutObject
	// SignerID must be the origin ID from networking layer, which cryptographically
	//  authenticates the message's sender.
	SignerID flow.Identifier
	// SigData is a BLS signature created by staking key signing View + NewestQC.View
	// This signature is further aggregated in TimeoutCertificate.
	SigData crypto.Signature
	// TimeoutTick is the number of times the `timeout.Controller` has (re-)emitted the
	// timeout for this view. When the timer for the view's original duration expires, a `TimeoutObject`
	// with `TimeoutTick = 0` is broadcast. Subsequently, `timeout.Controller` re-broadcasts the
	// `TimeoutObject` periodically  based on some internal heuristic. Each time we attempt a re-broadcast,
	// the `TimeoutTick` is incremented. Incrementing the field prevents de-duplicated within the network layer,
	// which in turn guarantees quick delivery of the `TimeoutObject` after GST and facilitates recovery.
	// This field is not part of timeout object ID. Thereby, two timeouts are identical if only they differ
	// by their TimeoutTick value.
	TimeoutTick uint64
}

TimeoutObject represents intent of replica to leave its current view with a timeout. This concept is very similar to HotStuff vote. Valid TimeoutObject is signed by staking key.

func (*TimeoutObject) ID added in v0.29.0

func (t *TimeoutObject) ID() flow.Identifier

ID returns the TimeoutObject's identifier

func (*TimeoutObject) LogContext added in v0.29.0

func (t *TimeoutObject) LogContext(logger zerolog.Logger) zerolog.Context

LogContext returns a `zerolog.Contex` including the most important properties of the TC:

  • view number that this TC is for
  • view and ID of the block that the included QC points to
  • number of times a re-broadcast of this timeout was attempted
  • [optional] if the TC also includes a TC for the prior view, i.e. `LastViewTC` ≠ nil: the new of `LastViewTC` and the view that `LastViewTC.NewestQC` is for

func (*TimeoutObject) String added in v0.29.0

func (t *TimeoutObject) String() string

type TimerInfo

type TimerInfo struct {
	// View is round at which timer was created.
	View uint64
	// StartTime represents time of entering the view.
	StartTime time.Time
	// Duration is how long we waited before timing out the view.
	// It does not include subsequent timeouts (ie. all timeout events emitted for the same
	// view will have the same Duration).
	Duration time.Duration
}

TimerInfo represents a local timeout for a view, and indicates the Pacemaker has not yet observed evidence to transition to the next view (QC or TC). When a timeout occurs for the first time in a view, we will broadcast a TimeoutObject and continue waiting for evidence to enter the next view, but we will no longer submit a vote for this view. A timeout may occur multiple times for the same round, which is an indication to re-broadcast our TimeoutObject for the view, to ensure liveness.

type Vote

type Vote struct {
	View     uint64
	BlockID  flow.Identifier
	SignerID flow.Identifier
	SigData  []byte
}

Vote is the HotStuff algorithm's concept of a vote for a block proposal.

func VoteFromFlow

func VoteFromFlow(signerID flow.Identifier, blockID flow.Identifier, view uint64, sig crypto.Signature) *Vote

VoteFromFlow turns the vote parameters into a vote struct.

func (*Vote) ID

func (uv *Vote) ID() flow.Identifier

ID returns the identifier for the vote.

Jump to

Keyboard shortcuts

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