mirror of https://github.com/poanetwork/gecko.git
Added switch for temporary and permanent errors in proposal blocks
This commit is contained in:
parent
f8c202e4be
commit
8ed43f464c
|
@ -24,7 +24,9 @@ func (a *Abort) Verify() error {
|
|||
// Abort is a decision, so its parent must be a proposal
|
||||
if !ok {
|
||||
if err := a.Reject(); err == nil {
|
||||
a.vm.DB.Commit()
|
||||
if err := a.vm.DB.Commit(); err != nil {
|
||||
a.vm.Ctx.Log.Error("error committing Abort block as rejected: %s", err)
|
||||
}
|
||||
} else {
|
||||
a.vm.DB.Abort()
|
||||
}
|
||||
|
|
|
@ -56,41 +56,41 @@ func (tx *addDefaultSubnetDelegatorTx) ID() ids.ID { return tx.id }
|
|||
|
||||
// SyntacticVerify return nil iff [tx] is valid
|
||||
// If [tx] is valid, sets [tx.accountID]
|
||||
func (tx *addDefaultSubnetDelegatorTx) SyntacticVerify() error {
|
||||
func (tx *addDefaultSubnetDelegatorTx) SyntacticVerify() TxError {
|
||||
switch {
|
||||
case tx == nil:
|
||||
return errNilTx
|
||||
return tempError{errNilTx}
|
||||
case !tx.senderID.IsZero():
|
||||
return nil // Only verify the transaction once
|
||||
case tx.id.IsZero():
|
||||
return errInvalidID
|
||||
return tempError{errInvalidID}
|
||||
case tx.NetworkID != tx.vm.Ctx.NetworkID:
|
||||
return errWrongNetworkID
|
||||
return permError{errWrongNetworkID}
|
||||
case tx.NodeID.IsZero():
|
||||
return errInvalidID
|
||||
return tempError{errInvalidID}
|
||||
case tx.Wght < MinimumStakeAmount: // Ensure validator is staking at least the minimum amount
|
||||
return errWeightTooSmall
|
||||
return permError{errWeightTooSmall}
|
||||
}
|
||||
|
||||
// Ensure staking length is not too short or long
|
||||
stakingDuration := tx.Duration()
|
||||
if stakingDuration < MinimumStakingDuration {
|
||||
return errStakeTooShort
|
||||
return permError{errStakeTooShort}
|
||||
} else if stakingDuration > MaximumStakingDuration {
|
||||
return errStakeTooLong
|
||||
return permError{errStakeTooLong}
|
||||
}
|
||||
|
||||
unsignedIntf := interface{}(&tx.UnsignedAddDefaultSubnetDelegatorTx)
|
||||
// Byte representation of the unsigned transaction
|
||||
unsignedBytes, err := Codec.Marshal(&unsignedIntf)
|
||||
if err != nil {
|
||||
return err
|
||||
return permError{err}
|
||||
}
|
||||
|
||||
// get account to pay tx fee from
|
||||
key, err := tx.vm.factory.RecoverPublicKey(unsignedBytes, tx.Sig[:])
|
||||
if err != nil {
|
||||
return err
|
||||
return permError{err}
|
||||
}
|
||||
tx.senderID = key.Address()
|
||||
|
||||
|
@ -98,7 +98,7 @@ func (tx *addDefaultSubnetDelegatorTx) SyntacticVerify() error {
|
|||
}
|
||||
|
||||
// SemanticVerify this transaction is valid.
|
||||
func (tx *addDefaultSubnetDelegatorTx) SemanticVerify(db database.Database) (*versiondb.Database, *versiondb.Database, func(), func(), error) {
|
||||
func (tx *addDefaultSubnetDelegatorTx) SemanticVerify(db database.Database) (*versiondb.Database, *versiondb.Database, func(), func(), TxError) {
|
||||
if err := tx.SyntacticVerify(); err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
|
@ -106,60 +106,62 @@ func (tx *addDefaultSubnetDelegatorTx) SemanticVerify(db database.Database) (*ve
|
|||
// Ensure the proposed validator starts after the current timestamp
|
||||
currentTimestamp, err := tx.vm.getTimestamp(db)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
validatorStartTime := tx.StartTime()
|
||||
if !currentTimestamp.Before(validatorStartTime) {
|
||||
return nil, nil, nil, nil, fmt.Errorf("chain timestamp (%s) not before validator's start time (%s)",
|
||||
return nil, nil, nil, nil, permError{fmt.Errorf("chain timestamp (%s) not before validator's start time (%s)",
|
||||
currentTimestamp,
|
||||
validatorStartTime)
|
||||
validatorStartTime)}
|
||||
}
|
||||
|
||||
// Get the account that is paying the transaction fee and, if the proposal is to add a validator
|
||||
// to the default subnet, providing the staked $AVA.
|
||||
// The ID of this account is the address associated with the public key that signed this tx
|
||||
// Get the account that is paying the transaction fee and, if the proposal
|
||||
// is to add a validator to the default subnet, providing the staked $AVA.
|
||||
// The ID of this account is the address associated with the public key that
|
||||
// signed this tx.
|
||||
accountID := tx.senderID
|
||||
account, err := tx.vm.getAccount(db, accountID)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errDBAccount
|
||||
return nil, nil, nil, nil, permError{errDBAccount}
|
||||
}
|
||||
|
||||
// The account if this block's proposal is committed and the validator is added
|
||||
// to the pending validator set. (Increase the account's nonce; decrease its balance.)
|
||||
// The account if this block's proposal is committed and the validator is
|
||||
// added to the pending validator set. (Increase the account's nonce;
|
||||
// decrease its balance.)
|
||||
newAccount, err := account.Remove(0, tx.Nonce) // Remove also removes the fee
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
|
||||
// Ensure that the period this validator validates the specified subnet is a subnet of the time they validate the default subnet
|
||||
// First, see if they're currently validating the default subnet
|
||||
currentEvents, err := tx.vm.getCurrentValidators(db, DefaultSubnetID)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, fmt.Errorf("couldn't get current validators of default subnet: %v", err)
|
||||
return nil, nil, nil, nil, permError{fmt.Errorf("couldn't get current validators of default subnet: %v", err)}
|
||||
}
|
||||
if dsValidator, err := currentEvents.getDefaultSubnetStaker(tx.NodeID); err == nil {
|
||||
if !tx.DurationValidator.BoundedBy(dsValidator.StartTime(), dsValidator.EndTime()) {
|
||||
return nil, nil, nil, nil, errDSValidatorSubset
|
||||
return nil, nil, nil, nil, permError{errDSValidatorSubset}
|
||||
}
|
||||
} else {
|
||||
// They aren't currently validating the default subnet.
|
||||
// See if they will validate the default subnet in the future.
|
||||
pendingDSValidators, err := tx.vm.getPendingValidators(db, DefaultSubnetID)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, fmt.Errorf("couldn't get pending validators of default subnet: %v", err)
|
||||
return nil, nil, nil, nil, permError{fmt.Errorf("couldn't get pending validators of default subnet: %v", err)}
|
||||
}
|
||||
dsValidator, err := pendingDSValidators.getDefaultSubnetStaker(tx.NodeID)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errDSValidatorSubset
|
||||
return nil, nil, nil, nil, permError{errDSValidatorSubset}
|
||||
}
|
||||
if !tx.DurationValidator.BoundedBy(dsValidator.StartTime(), dsValidator.EndTime()) {
|
||||
return nil, nil, nil, nil, errDSValidatorSubset
|
||||
return nil, nil, nil, nil, permError{errDSValidatorSubset}
|
||||
}
|
||||
}
|
||||
|
||||
pendingEvents, err := tx.vm.getPendingValidators(db, DefaultSubnetID)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
|
||||
pendingEvents.Add(tx) // add validator to set of pending validators
|
||||
|
@ -168,10 +170,10 @@ func (tx *addDefaultSubnetDelegatorTx) SemanticVerify(db database.Database) (*ve
|
|||
// update the validator's account by removing the staked $AVA
|
||||
onCommitDB := versiondb.New(db)
|
||||
if err := tx.vm.putPendingValidators(onCommitDB, pendingEvents, DefaultSubnetID); err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
if err := tx.vm.putAccount(onCommitDB, newAccount); err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
|
||||
// If this proposal is aborted, chain state doesn't change
|
||||
|
|
|
@ -63,44 +63,44 @@ func (tx *addDefaultSubnetValidatorTx) ID() ids.ID { return tx.id }
|
|||
|
||||
// SyntacticVerify that this transaction is well formed
|
||||
// If [tx] is valid, this method also populates [tx.accountID]
|
||||
func (tx *addDefaultSubnetValidatorTx) SyntacticVerify() error {
|
||||
func (tx *addDefaultSubnetValidatorTx) SyntacticVerify() TxError {
|
||||
switch {
|
||||
case tx == nil:
|
||||
return errNilTx
|
||||
return tempError{errNilTx}
|
||||
case !tx.senderID.IsZero():
|
||||
return nil // Only verify the transaction once
|
||||
case tx.id.IsZero():
|
||||
return errInvalidID
|
||||
return tempError{errInvalidID}
|
||||
case tx.NetworkID != tx.vm.Ctx.NetworkID:
|
||||
return errWrongNetworkID
|
||||
return permError{errWrongNetworkID}
|
||||
case tx.NodeID.IsZero():
|
||||
return errInvalidID
|
||||
return tempError{errInvalidID}
|
||||
case tx.Destination.IsZero():
|
||||
return errInvalidID
|
||||
return tempError{errInvalidID}
|
||||
case tx.Wght < MinimumStakeAmount: // Ensure validator is staking at least the minimum amount
|
||||
return errWeightTooSmall
|
||||
return permError{errWeightTooSmall}
|
||||
case tx.Shares > NumberOfShares: // Ensure delegators shares are in the allowed amount
|
||||
return errTooManyShares
|
||||
return permError{errTooManyShares}
|
||||
}
|
||||
|
||||
// Ensure staking length is not too short or long
|
||||
stakingDuration := tx.Duration()
|
||||
if stakingDuration < MinimumStakingDuration {
|
||||
return errStakeTooShort
|
||||
return permError{errStakeTooShort}
|
||||
} else if stakingDuration > MaximumStakingDuration {
|
||||
return errStakeTooLong
|
||||
return permError{errStakeTooLong}
|
||||
}
|
||||
|
||||
// Byte representation of the unsigned transaction
|
||||
unsignedIntf := interface{}(&tx.UnsignedAddDefaultSubnetValidatorTx)
|
||||
unsignedBytes, err := Codec.Marshal(&unsignedIntf)
|
||||
if err != nil {
|
||||
return err
|
||||
return permError{err}
|
||||
}
|
||||
|
||||
key, err := tx.vm.factory.RecoverPublicKey(unsignedBytes, tx.Sig[:]) // the public key that signed [tx]
|
||||
if err != nil {
|
||||
return err
|
||||
return permError{err}
|
||||
}
|
||||
tx.senderID = key.Address()
|
||||
|
||||
|
@ -108,7 +108,7 @@ func (tx *addDefaultSubnetValidatorTx) SyntacticVerify() error {
|
|||
}
|
||||
|
||||
// SemanticVerify this transaction is valid.
|
||||
func (tx *addDefaultSubnetValidatorTx) SemanticVerify(db database.Database) (*versiondb.Database, *versiondb.Database, func(), func(), error) {
|
||||
func (tx *addDefaultSubnetValidatorTx) SemanticVerify(db database.Database) (*versiondb.Database, *versiondb.Database, func(), func(), TxError) {
|
||||
if err := tx.SyntacticVerify(); err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
|
@ -116,13 +116,13 @@ func (tx *addDefaultSubnetValidatorTx) SemanticVerify(db database.Database) (*ve
|
|||
// Ensure the proposed validator starts after the current time
|
||||
currentTime, err := tx.vm.getTimestamp(db)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
startTime := tx.StartTime()
|
||||
if !currentTime.Before(startTime) {
|
||||
return nil, nil, nil, nil, fmt.Errorf("chain timestamp (%s) not before validator's start time (%s)",
|
||||
return nil, nil, nil, nil, permError{fmt.Errorf("chain timestamp (%s) not before validator's start time (%s)",
|
||||
currentTime,
|
||||
startTime)
|
||||
startTime)}
|
||||
}
|
||||
|
||||
// Get the account that is paying the transaction fee and, if the proposal is to add a validator
|
||||
|
@ -131,7 +131,7 @@ func (tx *addDefaultSubnetValidatorTx) SemanticVerify(db database.Database) (*ve
|
|||
accountID := tx.senderID
|
||||
account, err := tx.vm.getAccount(db, accountID)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errDBAccount
|
||||
return nil, nil, nil, nil, permError{errDBAccount}
|
||||
}
|
||||
|
||||
// If the transaction adds a validator to the default subnet, also deduct
|
||||
|
@ -142,31 +142,31 @@ func (tx *addDefaultSubnetValidatorTx) SemanticVerify(db database.Database) (*ve
|
|||
// to the pending validator set. (Increase the account's nonce; decrease its balance.)
|
||||
newAccount, err := account.Remove(amount, tx.Nonce)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
|
||||
// Ensure the proposed validator is not already a validator of the specified subnet
|
||||
currentEvents, err := tx.vm.getCurrentValidators(db, DefaultSubnetID)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
currentValidators := validators.NewSet()
|
||||
currentValidators.Set(tx.vm.getValidators(currentEvents))
|
||||
if currentValidators.Contains(tx.NodeID) {
|
||||
return nil, nil, nil, nil, fmt.Errorf("validator with ID %s already in the current default validator set",
|
||||
tx.NodeID)
|
||||
return nil, nil, nil, nil, permError{fmt.Errorf("validator with ID %s already in the current default validator set",
|
||||
tx.NodeID)}
|
||||
}
|
||||
|
||||
// Ensure the proposed validator is not already slated to validate for the specified subnet
|
||||
pendingEvents, err := tx.vm.getPendingValidators(db, DefaultSubnetID)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
pendingValidators := validators.NewSet()
|
||||
pendingValidators.Set(tx.vm.getValidators(pendingEvents))
|
||||
if pendingValidators.Contains(tx.NodeID) {
|
||||
return nil, nil, nil, nil, fmt.Errorf("validator with ID %s already in the pending default validator set",
|
||||
tx.NodeID)
|
||||
return nil, nil, nil, nil, permError{fmt.Errorf("validator with ID %s already in the pending default validator set",
|
||||
tx.NodeID)}
|
||||
}
|
||||
|
||||
pendingEvents.Add(tx) // add validator to set of pending validators
|
||||
|
@ -175,10 +175,10 @@ func (tx *addDefaultSubnetValidatorTx) SemanticVerify(db database.Database) (*ve
|
|||
// update the validator's account by removing the staked $AVA
|
||||
onCommitDB := versiondb.New(db)
|
||||
if err := tx.vm.putPendingValidators(onCommitDB, pendingEvents, DefaultSubnetID); err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
if err := tx.vm.putAccount(onCommitDB, newAccount); err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
|
||||
// If this proposal is aborted, chain state doesn't change
|
||||
|
|
|
@ -77,39 +77,39 @@ func (tx *addNonDefaultSubnetValidatorTx) ID() ids.ID { return tx.id }
|
|||
|
||||
// SyntacticVerify return nil iff [tx] is valid
|
||||
// If [tx] is valid, sets [tx.accountID]
|
||||
func (tx *addNonDefaultSubnetValidatorTx) SyntacticVerify() error {
|
||||
func (tx *addNonDefaultSubnetValidatorTx) SyntacticVerify() TxError {
|
||||
switch {
|
||||
case tx == nil:
|
||||
return errNilTx
|
||||
return tempError{errNilTx}
|
||||
case !tx.senderID.IsZero():
|
||||
return nil // Only verify the transaction once
|
||||
case tx.id.IsZero():
|
||||
return errInvalidID
|
||||
return tempError{errInvalidID}
|
||||
case tx.NetworkID != tx.vm.Ctx.NetworkID:
|
||||
return errWrongNetworkID
|
||||
return permError{errWrongNetworkID}
|
||||
case tx.NodeID.IsZero():
|
||||
return errInvalidID
|
||||
return tempError{errInvalidID}
|
||||
case tx.Subnet.IsZero():
|
||||
return errInvalidID
|
||||
return tempError{errInvalidID}
|
||||
case tx.Wght == 0: // Ensure the validator has some weight
|
||||
return errWeightTooSmall
|
||||
return permError{errWeightTooSmall}
|
||||
case !crypto.IsSortedAndUniqueSECP2561RSigs(tx.ControlSigs):
|
||||
return errSigsNotSorted
|
||||
return permError{errSigsNotSorted}
|
||||
}
|
||||
|
||||
// Ensure staking length is not too short or long
|
||||
stakingDuration := tx.Duration()
|
||||
if stakingDuration < MinimumStakingDuration {
|
||||
return errStakeTooShort
|
||||
return permError{errStakeTooShort}
|
||||
} else if stakingDuration > MaximumStakingDuration {
|
||||
return errStakeTooLong
|
||||
return permError{errStakeTooLong}
|
||||
}
|
||||
|
||||
// Byte representation of the unsigned transaction
|
||||
unsignedIntf := interface{}(&tx.UnsignedAddNonDefaultSubnetValidatorTx)
|
||||
unsignedBytes, err := Codec.Marshal(&unsignedIntf)
|
||||
if err != nil {
|
||||
return err
|
||||
return permError{err}
|
||||
}
|
||||
unsignedBytesHash := hashing.ComputeHash256(unsignedBytes)
|
||||
|
||||
|
@ -118,7 +118,7 @@ func (tx *addNonDefaultSubnetValidatorTx) SyntacticVerify() error {
|
|||
for i, sig := range tx.ControlSigs {
|
||||
key, err := tx.vm.factory.RecoverHashPublicKey(unsignedBytesHash, sig[:])
|
||||
if err != nil {
|
||||
return err
|
||||
return permError{err}
|
||||
}
|
||||
tx.controlIDs[i] = key.Address()
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ func (tx *addNonDefaultSubnetValidatorTx) SyntacticVerify() error {
|
|||
// get account to pay tx fee from
|
||||
key, err := tx.vm.factory.RecoverHashPublicKey(unsignedBytesHash, tx.PayerSig[:])
|
||||
if err != nil {
|
||||
return err
|
||||
return permError{err}
|
||||
}
|
||||
tx.senderID = key.Address()
|
||||
|
||||
|
@ -149,7 +149,7 @@ func (h *EventHeap) getDefaultSubnetStaker(id ids.ShortID) (*addDefaultSubnetVal
|
|||
}
|
||||
|
||||
// SemanticVerify this transaction is valid.
|
||||
func (tx *addNonDefaultSubnetValidatorTx) SemanticVerify(db database.Database) (*versiondb.Database, *versiondb.Database, func(), func(), error) {
|
||||
func (tx *addNonDefaultSubnetValidatorTx) SemanticVerify(db database.Database) (*versiondb.Database, *versiondb.Database, func(), func(), TxError) {
|
||||
// Ensure tx is syntactically valid
|
||||
if err := tx.SyntacticVerify(); err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
|
@ -158,7 +158,7 @@ func (tx *addNonDefaultSubnetValidatorTx) SemanticVerify(db database.Database) (
|
|||
// Get info about the subnet we're adding a validator to
|
||||
subnets, err := tx.vm.getSubnets(db)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
var subnet *CreateSubnetTx
|
||||
for _, sn := range subnets {
|
||||
|
@ -168,22 +168,22 @@ func (tx *addNonDefaultSubnetValidatorTx) SemanticVerify(db database.Database) (
|
|||
}
|
||||
}
|
||||
if subnet == nil {
|
||||
return nil, nil, nil, nil, fmt.Errorf("there is no subnet with ID %s", tx.SubnetID())
|
||||
return nil, nil, nil, nil, permError{fmt.Errorf("there is no subnet with ID %s", tx.SubnetID())}
|
||||
}
|
||||
|
||||
// Ensure the sigs on [tx] are valid
|
||||
if len(tx.ControlSigs) != int(subnet.Threshold) {
|
||||
return nil, nil, nil, nil, fmt.Errorf("expected tx to have %d control sigs but has %d", subnet.Threshold, len(tx.ControlSigs))
|
||||
return nil, nil, nil, nil, permError{fmt.Errorf("expected tx to have %d control sigs but has %d", subnet.Threshold, len(tx.ControlSigs))}
|
||||
}
|
||||
if !crypto.IsSortedAndUniqueSECP2561RSigs(tx.ControlSigs) {
|
||||
return nil, nil, nil, nil, errors.New("control signatures aren't sorted")
|
||||
return nil, nil, nil, nil, permError{errors.New("control signatures aren't sorted")}
|
||||
}
|
||||
|
||||
controlKeys := ids.ShortSet{}
|
||||
controlKeys.Add(subnet.ControlKeys...)
|
||||
for _, controlID := range tx.controlIDs {
|
||||
if !controlKeys.Contains(controlID) {
|
||||
return nil, nil, nil, nil, errors.New("tx has control signature from key not in subnet's ControlKeys")
|
||||
return nil, nil, nil, nil, permError{errors.New("tx has control signature from key not in subnet's ControlKeys")}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,46 +191,46 @@ func (tx *addNonDefaultSubnetValidatorTx) SemanticVerify(db database.Database) (
|
|||
// First, see if they're currently validating the default subnet
|
||||
currentDSValidators, err := tx.vm.getCurrentValidators(db, DefaultSubnetID)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, fmt.Errorf("couldn't get current validators of default subnet: %v", err)
|
||||
return nil, nil, nil, nil, permError{fmt.Errorf("couldn't get current validators of default subnet: %v", err)}
|
||||
}
|
||||
|
||||
if dsValidator, err := currentDSValidators.getDefaultSubnetStaker(tx.NodeID); err == nil {
|
||||
if !tx.DurationValidator.BoundedBy(dsValidator.StartTime(), dsValidator.EndTime()) {
|
||||
return nil, nil, nil, nil,
|
||||
fmt.Errorf("time validating subnet [%v, %v] not subset of time validating default subnet [%v, %v]",
|
||||
permError{fmt.Errorf("time validating subnet [%v, %v] not subset of time validating default subnet [%v, %v]",
|
||||
tx.DurationValidator.StartTime(), tx.DurationValidator.EndTime(),
|
||||
dsValidator.StartTime(), dsValidator.EndTime())
|
||||
dsValidator.StartTime(), dsValidator.EndTime())}
|
||||
}
|
||||
} else {
|
||||
// They aren't currently validating the default subnet.
|
||||
// See if they will validate the default subnet in the future.
|
||||
pendingDSValidators, err := tx.vm.getPendingValidators(db, DefaultSubnetID)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, fmt.Errorf("couldn't get pending validators of default subnet: %v", err)
|
||||
return nil, nil, nil, nil, permError{fmt.Errorf("couldn't get pending validators of default subnet: %v", err)}
|
||||
}
|
||||
dsValidator, err := pendingDSValidators.getDefaultSubnetStaker(tx.NodeID)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil,
|
||||
fmt.Errorf("validator would not be validating default subnet while validating non-default subnet")
|
||||
permError{fmt.Errorf("validator would not be validating default subnet while validating non-default subnet")}
|
||||
}
|
||||
if !tx.DurationValidator.BoundedBy(dsValidator.StartTime(), dsValidator.EndTime()) {
|
||||
return nil, nil, nil, nil,
|
||||
fmt.Errorf("time validating subnet [%v, %v] not subset of time validating default subnet [%v, %v]",
|
||||
permError{fmt.Errorf("time validating subnet [%v, %v] not subset of time validating default subnet [%v, %v]",
|
||||
tx.DurationValidator.StartTime(), tx.DurationValidator.EndTime(),
|
||||
dsValidator.StartTime(), dsValidator.EndTime())
|
||||
dsValidator.StartTime(), dsValidator.EndTime())}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the proposed validator starts after the current timestamp
|
||||
currentTimestamp, err := tx.vm.getTimestamp(db)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, fmt.Errorf("couldn't get current timestamp: %v", err)
|
||||
return nil, nil, nil, nil, permError{fmt.Errorf("couldn't get current timestamp: %v", err)}
|
||||
}
|
||||
validatorStartTime := tx.StartTime()
|
||||
if !currentTimestamp.Before(validatorStartTime) {
|
||||
return nil, nil, nil, nil, fmt.Errorf("chain timestamp (%s) not before validator's start time (%s)",
|
||||
return nil, nil, nil, nil, permError{fmt.Errorf("chain timestamp (%s) not before validator's start time (%s)",
|
||||
currentTimestamp,
|
||||
validatorStartTime)
|
||||
validatorStartTime)}
|
||||
}
|
||||
|
||||
// Get the account that is paying the transaction fee and, if the proposal is to add a validator
|
||||
|
@ -239,42 +239,40 @@ func (tx *addNonDefaultSubnetValidatorTx) SemanticVerify(db database.Database) (
|
|||
accountID := tx.senderID
|
||||
account, err := tx.vm.getAccount(db, accountID)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errDBAccount
|
||||
return nil, nil, nil, nil, permError{errDBAccount}
|
||||
}
|
||||
|
||||
// The account if this block's proposal is committed and the validator is added
|
||||
// to the pending validator set. (Increase the account's nonce; decrease its balance.)
|
||||
newAccount, err := account.Remove(0, tx.Nonce) // Remove also removes the fee
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
|
||||
// Ensure the proposed validator is not already a validator of the specified subnet
|
||||
currentEvents, err := tx.vm.getCurrentValidators(db, tx.Subnet)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, fmt.Errorf("couldn't get current validators of subnet %s: %v", tx.Subnet, err)
|
||||
return nil, nil, nil, nil, permError{fmt.Errorf("couldn't get current validators of subnet %s: %v", tx.Subnet, err)}
|
||||
}
|
||||
currentValidators := validators.NewSet()
|
||||
currentValidators.Set(tx.vm.getValidators(currentEvents))
|
||||
if currentValidators.Contains(tx.NodeID) {
|
||||
return nil, nil, nil, nil, fmt.Errorf("validator with ID %s already in the current validator set for subnet with ID %s",
|
||||
return nil, nil, nil, nil, permError{fmt.Errorf("validator with ID %s already in the current validator set for subnet with ID %s",
|
||||
tx.NodeID,
|
||||
tx.Subnet,
|
||||
)
|
||||
tx.Subnet)}
|
||||
}
|
||||
|
||||
// Ensure the proposed validator is not already slated to validate for the specified subnet
|
||||
pendingEvents, err := tx.vm.getPendingValidators(db, tx.Subnet)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, fmt.Errorf("couldn't get pending validators of subnet %s: %v", tx.Subnet, err)
|
||||
return nil, nil, nil, nil, permError{fmt.Errorf("couldn't get pending validators of subnet %s: %v", tx.Subnet, err)}
|
||||
}
|
||||
pendingValidators := validators.NewSet()
|
||||
pendingValidators.Set(tx.vm.getValidators(pendingEvents))
|
||||
if pendingValidators.Contains(tx.NodeID) {
|
||||
return nil, nil, nil, nil, fmt.Errorf("validator with ID %s already in the pending validator set for subnet with ID %s",
|
||||
return nil, nil, nil, nil, permError{fmt.Errorf("validator with ID %s already in the pending validator set for subnet with ID %s",
|
||||
tx.NodeID,
|
||||
tx.Subnet,
|
||||
)
|
||||
tx.Subnet)}
|
||||
}
|
||||
|
||||
pendingEvents.Add(tx) // add validator to set of pending validators
|
||||
|
@ -283,10 +281,10 @@ func (tx *addNonDefaultSubnetValidatorTx) SemanticVerify(db database.Database) (
|
|||
// update the validator's account by removing the staked $AVA
|
||||
onCommitDB := versiondb.New(db)
|
||||
if err := tx.vm.putPendingValidators(onCommitDB, pendingEvents, tx.Subnet); err != nil {
|
||||
return nil, nil, nil, nil, fmt.Errorf("couldn't put current validators: %v", err)
|
||||
return nil, nil, nil, nil, permError{fmt.Errorf("couldn't put current validators: %v", err)}
|
||||
}
|
||||
if err := tx.vm.putAccount(onCommitDB, newAccount); err != nil {
|
||||
return nil, nil, nil, nil, fmt.Errorf("couldn't put account: %v", err)
|
||||
return nil, nil, nil, nil, permError{fmt.Errorf("couldn't put account: %v", err)}
|
||||
}
|
||||
|
||||
// If this proposal is aborted, chain state doesn't change
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
package platformvm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
|
@ -35,47 +36,47 @@ func (tx *advanceTimeTx) initialize(vm *VM) error {
|
|||
func (tx *advanceTimeTx) Timestamp() time.Time { return time.Unix(int64(tx.Time), 0) }
|
||||
|
||||
// SyntacticVerify that this transaction is well formed
|
||||
func (tx *advanceTimeTx) SyntacticVerify() error {
|
||||
func (tx *advanceTimeTx) SyntacticVerify() TxError {
|
||||
switch {
|
||||
case tx == nil:
|
||||
return errNilTx
|
||||
return tempError{errNilTx}
|
||||
case tx.vm.clock.Time().Add(Delta).Before(tx.Timestamp()):
|
||||
return errTimeTooAdvanced
|
||||
return tempError{errTimeTooAdvanced}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// SemanticVerify this transaction is valid.
|
||||
func (tx *advanceTimeTx) SemanticVerify(db database.Database) (*versiondb.Database, *versiondb.Database, func(), func(), error) {
|
||||
func (tx *advanceTimeTx) SemanticVerify(db database.Database) (*versiondb.Database, *versiondb.Database, func(), func(), TxError) {
|
||||
if err := tx.SyntacticVerify(); err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
|
||||
currentTimestamp, err := tx.vm.getTimestamp(db)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
if tx.Time <= uint64(currentTimestamp.Unix()) {
|
||||
return nil, nil, nil, nil, fmt.Errorf("proposed timestamp %s not after current timestamp %s",
|
||||
return nil, nil, nil, nil, permError{fmt.Errorf("proposed timestamp %s not after current timestamp %s",
|
||||
tx.Timestamp(),
|
||||
currentTimestamp)
|
||||
currentTimestamp)}
|
||||
}
|
||||
|
||||
// Only allow timestamp to move forward as far as the next validator's end time
|
||||
nextValidatorEndTime := tx.vm.nextValidatorChangeTime(db, false)
|
||||
if tx.Time > uint64(nextValidatorEndTime.Unix()) {
|
||||
return nil, nil, nil, nil, fmt.Errorf("proposed timestamp %v later than next validator end time %s",
|
||||
return nil, nil, nil, nil, permError{fmt.Errorf("proposed timestamp %v later than next validator end time %s",
|
||||
tx.Time,
|
||||
nextValidatorEndTime)
|
||||
nextValidatorEndTime)}
|
||||
}
|
||||
|
||||
// Only allow timestamp to move forward as far as the next pending validator's start time
|
||||
nextValidatorStartTime := tx.vm.nextValidatorChangeTime(db, true)
|
||||
if tx.Time > uint64(nextValidatorStartTime.Unix()) {
|
||||
return nil, nil, nil, nil, fmt.Errorf("proposed timestamp %v later than next validator start time %s",
|
||||
return nil, nil, nil, nil, permError{fmt.Errorf("proposed timestamp %v later than next validator start time %s",
|
||||
tx.Time,
|
||||
nextValidatorStartTime)
|
||||
nextValidatorStartTime)}
|
||||
}
|
||||
|
||||
// Calculate what the validator sets will be given new timestamp
|
||||
|
@ -85,19 +86,19 @@ func (tx *advanceTimeTx) SemanticVerify(db database.Database) (*versiondb.Databa
|
|||
// Specify what the state of the chain will be if this proposal is committed
|
||||
onCommitDB := versiondb.New(db)
|
||||
if err := tx.vm.putTimestamp(onCommitDB, tx.Timestamp()); err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
|
||||
current, pending, _, _, err := tx.vm.calculateValidators(db, tx.Timestamp(), DefaultSubnetID)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
|
||||
if err := tx.vm.putCurrentValidators(onCommitDB, current, DefaultSubnetID); err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
if err := tx.vm.putPendingValidators(onCommitDB, pending, DefaultSubnetID); err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
|
||||
// For each Subnet, calculate what current and pending validator sets should be
|
||||
|
@ -106,23 +107,23 @@ func (tx *advanceTimeTx) SemanticVerify(db database.Database) (*versiondb.Databa
|
|||
// Key: Subnet ID
|
||||
// Value: IDs of validators that will have started validating this Subnet when
|
||||
// timestamp is advanced to tx.Timestamp()
|
||||
startedValidating := make(map[ids.ID]ids.ShortSet, 0)
|
||||
startedValidating := make(map[[32]byte]ids.ShortSet, 0)
|
||||
subnets, err := tx.vm.getSubnets(db)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
for _, subnet := range subnets {
|
||||
current, pending, started, _, err := tx.vm.calculateValidators(db, tx.Timestamp(), subnet.id)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
if err := tx.vm.putCurrentValidators(onCommitDB, current, subnet.id); err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
if err := tx.vm.putPendingValidators(onCommitDB, pending, subnet.id); err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
startedValidating[subnet.ID()] = started
|
||||
startedValidating[subnet.ID().Key()] = started
|
||||
}
|
||||
|
||||
// If this block is committed, update the validator sets
|
||||
|
@ -154,7 +155,7 @@ func (tx *advanceTimeTx) SemanticVerify(db database.Database) (*versiondb.Databa
|
|||
continue
|
||||
}
|
||||
for _, chain := range chains {
|
||||
if chain.SubnetID.Equals(subnetID) {
|
||||
if bytes.Equal(subnetID[:], chain.SubnetID.Bytes()) {
|
||||
tx.vm.createChain(chain)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,9 @@ func (c *Commit) Verify() error {
|
|||
parent, ok := c.parentBlock().(*ProposalBlock)
|
||||
if !ok {
|
||||
if err := c.Reject(); err == nil {
|
||||
c.vm.DB.Commit()
|
||||
if err := c.vm.DB.Commit(); err != nil {
|
||||
c.vm.Ctx.Log.Error("error committing Commit block as rejected: %s", err)
|
||||
}
|
||||
} else {
|
||||
c.vm.DB.Abort()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
|
||||
package platformvm
|
||||
|
||||
// TxError provides the ability for errors to be distinguished as permenant or
|
||||
// temporary
|
||||
type TxError interface {
|
||||
error
|
||||
Temporary() bool
|
||||
}
|
||||
|
||||
type tempError struct{ error }
|
||||
|
||||
func (tempError) Temporary() bool { return true }
|
||||
|
||||
type permError struct{ error }
|
||||
|
||||
func (permError) Temporary() bool { return false }
|
|
@ -16,7 +16,13 @@ import (
|
|||
type ProposalTx interface {
|
||||
initialize(vm *VM) error
|
||||
// Attempts to verify this transaction with the provided state.
|
||||
SemanticVerify(database.Database) (onCommitDB *versiondb.Database, onAbortDB *versiondb.Database, onCommitFunc func(), onAbortFunc func(), err error)
|
||||
SemanticVerify(database.Database) (
|
||||
onCommitDB *versiondb.Database,
|
||||
onAbortDB *versiondb.Database,
|
||||
onCommitFunc func(),
|
||||
onAbortFunc func(),
|
||||
err TxError,
|
||||
)
|
||||
InitiallyPrefersCommit() bool
|
||||
}
|
||||
|
||||
|
@ -99,7 +105,9 @@ func (pb *ProposalBlock) Verify() error {
|
|||
parent, ok := parentIntf.(decision)
|
||||
if !ok {
|
||||
if err := pb.Reject(); err == nil {
|
||||
pb.vm.DB.Commit()
|
||||
if err := pb.vm.DB.Commit(); err != nil {
|
||||
pb.vm.Ctx.Log.Error("error committing Proposal block as rejected: %s", err)
|
||||
}
|
||||
} else {
|
||||
pb.vm.DB.Abort()
|
||||
}
|
||||
|
@ -109,19 +117,16 @@ func (pb *ProposalBlock) Verify() error {
|
|||
// pdb is the database if this block's parent is accepted
|
||||
pdb := parent.onAccept()
|
||||
|
||||
isAdvanceTimeProposal := false
|
||||
switch pb.Tx.(type) {
|
||||
case *advanceTimeTx:
|
||||
isAdvanceTimeProposal = true
|
||||
}
|
||||
var err error
|
||||
var err TxError
|
||||
pb.onCommitDB, pb.onAbortDB, pb.onCommitFunc, pb.onAbortFunc, err = pb.Tx.SemanticVerify(pdb)
|
||||
if err != nil {
|
||||
// If this block's transaction proposes to advance the timestamp, the transaction may fail
|
||||
// verification now but be valid in the future, so don't (permanently) mark the block as rejected.
|
||||
if !isAdvanceTimeProposal {
|
||||
if !err.Temporary() {
|
||||
if err := pb.Reject(); err == nil {
|
||||
pb.vm.DB.Commit()
|
||||
if err := pb.vm.DB.Commit(); err != nil {
|
||||
pb.vm.Ctx.Log.Error("error committing Proposal block as rejected: %s", err)
|
||||
}
|
||||
} else {
|
||||
pb.vm.DB.Abort()
|
||||
}
|
||||
|
|
|
@ -41,12 +41,12 @@ func (tx *rewardValidatorTx) initialize(vm *VM) error {
|
|||
}
|
||||
|
||||
// SyntacticVerify that this transaction is well formed
|
||||
func (tx *rewardValidatorTx) SyntacticVerify() error {
|
||||
func (tx *rewardValidatorTx) SyntacticVerify() TxError {
|
||||
switch {
|
||||
case tx == nil:
|
||||
return errNilTx
|
||||
return tempError{errNilTx}
|
||||
case tx.TxID.IsZero():
|
||||
return errInvalidID
|
||||
return tempError{errInvalidID}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
@ -58,39 +58,39 @@ func (tx *rewardValidatorTx) SyntacticVerify() error {
|
|||
// The next validator to be removed must be the validator specified in this block.
|
||||
// The next validator to be removed must be have an end time equal to the current
|
||||
// chain timestamp.
|
||||
func (tx *rewardValidatorTx) SemanticVerify(db database.Database) (*versiondb.Database, *versiondb.Database, func(), func(), error) {
|
||||
func (tx *rewardValidatorTx) SemanticVerify(db database.Database) (*versiondb.Database, *versiondb.Database, func(), func(), TxError) {
|
||||
if err := tx.SyntacticVerify(); err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
if db == nil {
|
||||
return nil, nil, nil, nil, errDBNil
|
||||
return nil, nil, nil, nil, tempError{errDBNil}
|
||||
}
|
||||
|
||||
currentEvents, err := tx.vm.getCurrentValidators(db, DefaultSubnetID)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, errDBCurrentValidators
|
||||
return nil, nil, nil, nil, permError{errDBCurrentValidators}
|
||||
}
|
||||
if currentEvents.Len() == 0 { // there is no validator to remove
|
||||
return nil, nil, nil, nil, errEmptyValidatingSet
|
||||
return nil, nil, nil, nil, permError{errEmptyValidatingSet}
|
||||
}
|
||||
|
||||
vdrTx := currentEvents.Peek()
|
||||
|
||||
if txID := vdrTx.ID(); !txID.Equals(tx.TxID) {
|
||||
return nil, nil, nil, nil, fmt.Errorf("attempting to remove TxID: %s. Should be removing %s",
|
||||
return nil, nil, nil, nil, permError{fmt.Errorf("attempting to remove TxID: %s. Should be removing %s",
|
||||
tx.TxID,
|
||||
txID)
|
||||
txID)}
|
||||
}
|
||||
|
||||
// Verify that the chain's timestamp is the validator's end time
|
||||
currentTime, err := tx.vm.getTimestamp(db)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
if endTime := vdrTx.EndTime(); !endTime.Equal(currentTime) {
|
||||
return nil, nil, nil, nil, fmt.Errorf("attempting to remove TxID: %s before their end time %s",
|
||||
return nil, nil, nil, nil, permError{fmt.Errorf("attempting to remove TxID: %s before their end time %s",
|
||||
tx.TxID,
|
||||
endTime)
|
||||
endTime)}
|
||||
}
|
||||
|
||||
heap.Pop(currentEvents) // Remove validator from the validator set
|
||||
|
@ -99,14 +99,14 @@ func (tx *rewardValidatorTx) SemanticVerify(db database.Database) (*versiondb.Da
|
|||
// If this tx's proposal is committed, remove the validator from the validator set and update the
|
||||
// account balance to reflect the return of staked $AVA and their reward.
|
||||
if err := tx.vm.putCurrentValidators(onCommitDB, currentEvents, DefaultSubnetID); err != nil {
|
||||
return nil, nil, nil, nil, errDBPutCurrentValidators
|
||||
return nil, nil, nil, nil, permError{errDBPutCurrentValidators}
|
||||
}
|
||||
|
||||
onAbortDB := versiondb.New(db)
|
||||
// If this tx's proposal is aborted, remove the validator from the validator set and update the
|
||||
// account balance to reflect the return of staked $AVA. The validator receives no reward.
|
||||
if err := tx.vm.putCurrentValidators(onAbortDB, currentEvents, DefaultSubnetID); err != nil {
|
||||
return nil, nil, nil, nil, errDBPutCurrentValidators
|
||||
return nil, nil, nil, nil, permError{errDBPutCurrentValidators}
|
||||
}
|
||||
|
||||
switch vdrTx := vdrTx.(type) {
|
||||
|
@ -144,15 +144,15 @@ func (tx *rewardValidatorTx) SemanticVerify(db database.Database) (*versiondb.Da
|
|||
}
|
||||
|
||||
if err := tx.vm.putAccount(onCommitDB, accountWithReward); err != nil {
|
||||
return nil, nil, nil, nil, errDBPutAccount
|
||||
return nil, nil, nil, nil, tempError{errDBPutAccount}
|
||||
}
|
||||
if err := tx.vm.putAccount(onAbortDB, accountNoReward); err != nil {
|
||||
return nil, nil, nil, nil, errDBPutAccount
|
||||
return nil, nil, nil, nil, tempError{errDBPutAccount}
|
||||
}
|
||||
case *addDefaultSubnetDelegatorTx:
|
||||
parentTx, err := currentEvents.getDefaultSubnetStaker(vdrTx.NodeID)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
|
||||
duration := vdrTx.Duration()
|
||||
|
@ -201,10 +201,10 @@ func (tx *rewardValidatorTx) SemanticVerify(db database.Database) (*versiondb.Da
|
|||
}
|
||||
|
||||
if err := tx.vm.putAccount(onCommitDB, delegatorAccountWithReward); err != nil {
|
||||
return nil, nil, nil, nil, errDBPutAccount
|
||||
return nil, nil, nil, nil, tempError{errDBPutAccount}
|
||||
}
|
||||
if err := tx.vm.putAccount(onAbortDB, delegatorAccountNoReward); err != nil {
|
||||
return nil, nil, nil, nil, errDBPutAccount
|
||||
return nil, nil, nil, nil, tempError{errDBPutAccount}
|
||||
}
|
||||
|
||||
validatorAccountID := parentTx.Destination
|
||||
|
@ -225,10 +225,10 @@ func (tx *rewardValidatorTx) SemanticVerify(db database.Database) (*versiondb.Da
|
|||
}
|
||||
|
||||
if err := tx.vm.putAccount(onCommitDB, validatorAccountWithReward); err != nil {
|
||||
return nil, nil, nil, nil, errDBPutAccount
|
||||
return nil, nil, nil, nil, permError{errDBPutAccount}
|
||||
}
|
||||
default:
|
||||
return nil, nil, nil, nil, errShouldBeDSValidator
|
||||
return nil, nil, nil, nil, permError{errShouldBeDSValidator}
|
||||
}
|
||||
|
||||
// Regardless of whether this tx is committed or aborted, update the
|
||||
|
|
|
@ -390,6 +390,7 @@ func (service *Service) SampleValidators(_ *http.Request, args *SampleValidators
|
|||
*************** Get/Create Accounts ******************
|
||||
******************************************************
|
||||
*/
|
||||
|
||||
// GetAccountArgs are the arguments for calling GetAccount
|
||||
type GetAccountArgs struct {
|
||||
// Address of the account we want the information about
|
||||
|
|
|
@ -55,7 +55,9 @@ func (sb *StandardBlock) Verify() error {
|
|||
parent, ok := parentBlock.(decision)
|
||||
if !ok {
|
||||
if err := sb.Reject(); err == nil {
|
||||
sb.vm.DB.Commit()
|
||||
if err := sb.vm.DB.Commit(); err != nil {
|
||||
sb.vm.Ctx.Log.Error("error committing Standard block as rejected: %s", err)
|
||||
}
|
||||
} else {
|
||||
sb.vm.DB.Abort()
|
||||
}
|
||||
|
@ -70,7 +72,9 @@ func (sb *StandardBlock) Verify() error {
|
|||
onAccept, err := tx.SemanticVerify(sb.onAcceptDB)
|
||||
if err != nil {
|
||||
if err := sb.Reject(); err == nil {
|
||||
sb.vm.DB.Commit()
|
||||
if err := sb.vm.DB.Commit(); err != nil {
|
||||
sb.vm.Ctx.Log.Error("error committing Standard block as rejected: %s", err)
|
||||
}
|
||||
} else {
|
||||
sb.vm.DB.Abort()
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ type APIAccount struct {
|
|||
Balance json.Uint64 `json:"balance"`
|
||||
}
|
||||
|
||||
// FormattedAPIAccount is an APIAccount but allows for a formatted Address
|
||||
type FormattedAPIAccount struct {
|
||||
Address string `json:"address"`
|
||||
Nonce json.Uint64 `json:"nonce"`
|
||||
|
@ -76,6 +77,7 @@ type APIDefaultSubnetValidator struct {
|
|||
DelegationFeeRate json.Uint32 `json:"delegationFeeRate"`
|
||||
}
|
||||
|
||||
// FormattedAPIValidator allows for a formatted address
|
||||
type FormattedAPIValidator struct {
|
||||
StartTime json.Uint64 `json:"startTime"`
|
||||
EndTime json.Uint64 `json:"endTime"`
|
||||
|
|
|
@ -867,7 +867,7 @@ func (vm *VM) GetAtomicUTXOs(addrs ids.Set) ([]*ava.UTXO, error) {
|
|||
return utxos, nil
|
||||
}
|
||||
|
||||
// ParseAddr ...
|
||||
// ParseAddress ...
|
||||
func (vm *VM) ParseAddress(addrStr string) (ids.ShortID, error) {
|
||||
cb58 := formatting.CB58{}
|
||||
err := cb58.FromString(addrStr)
|
||||
|
@ -877,8 +877,8 @@ func (vm *VM) ParseAddress(addrStr string) (ids.ShortID, error) {
|
|||
return ids.ToShortID(cb58.Bytes)
|
||||
}
|
||||
|
||||
// Assumes addrID is not empty
|
||||
// FormatAddress ...
|
||||
// Assumes addrID is not empty
|
||||
func (vm *VM) FormatAddress(addrID ids.ShortID) string {
|
||||
return addrID.String()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue