Banff Changes
This document specifies the changes in Metal “Banff”, which will be released in MetalGo v1.9.x.
Block Changes
Apricot
Apricot allows the following block types with the following content:
- Standard Blocks may contain multiple transactions of the following types:
- CreateChainTx
- CreateSubnetTx
- ImportTx
- ExportTx
- Proposal Blocks may contain a single transaction of the following types:
- AddValidatorTx
- AddDelegatorTx
- AddSubnetValidatorTx
- RewardValidatorTx
- AdvanceTimeTx
- Options Blocks, that is Commit Block and Abort Block do not contain any transactions.
Each block has a header containing:
- ParentID
- Height
Banff
Banff allows the following block types with the following content:
Standard Blocks may contain multiple transactions of the following types:
- CreateChainTx
- CreateSubnetTx
- ImportTx
- ExportTx
- AddValidatorTx
- AddDelegatorTx
- AddSubnetValidatorTx
- RemoveSubnetValidatorTx
- TransformSubnetTx
- AddPermissionlessValidatorTx
- AddPermissionlessDelegatorTx
Proposal Blocks may contain a single transaction of the following types:
- RewardValidatorTx
Options blocks, that is Commit Block and Abort Block do not contain any transactions.
Note that each block has an header containing:
- ParentID
- Height
- Time
So the two main differences with respect to Apricot are:
- AddValidatorTx, AddDelegatorTx, AddSubnetValidatorTx are included into Standard Blocks rather than Proposal Blocks so that they don't need to be voted on (that is followed by a Commit/Abort Block).
- New Transaction types: RemoveSubnetValidatorTx, TransformSubnetTx, AddPermissionlessValidatorTx, and AddPermissionlessDelegatorTx have been added into Standard Blocks.
- Block timestamp is explicitly serialized into block header, to allow chain time update.
New Transactions
RemoveSubnetValidatorTx
type RemoveSubnetValidatorTx struct {
BaseTx `serialize:"true"`
// The node to remove from the subnet.
NodeID ids.NodeID `serialize:"true" json:"nodeID"`
// The subnet to remove the node from.
Subnet ids.ID `serialize:"true" json:"subnet"`
// Proves that the issuer has the right to remove the node from the subnet.
SubnetAuth verify.Verifiable `serialize:"true" json:"subnetAuthorization"`
}
TransformSubnetTx
type TransformSubnetTx struct {
// Metadata, inputs and outputs
BaseTx `serialize:"true"`
// ID of the Subnet to transform
// Restrictions:
// - Must not be the Primary Network ID
Subnet ids.ID `serialize:"true" json:"subnetID"`
// Asset to use when staking on the Subnet
// Restrictions:
// - Must not be the Empty ID
// - Must not be the METAL ID
AssetID ids.ID `serialize:"true" json:"assetID"`
// Amount to initially specify as the current supply
// Restrictions:
// - Must be > 0
InitialSupply uint64 `serialize:"true" json:"initialSupply"`
// Amount to specify as the maximum token supply
// Restrictions:
// - Must be >= [InitialSupply]
MaximumSupply uint64 `serialize:"true" json:"maximumSupply"`
// MinConsumptionRate is the rate to allocate funds if the validator's stake
// duration is 0
MinConsumptionRate uint64 `serialize:"true" json:"minConsumptionRate"`
// MaxConsumptionRate is the rate to allocate funds if the validator's stake
// duration is equal to the minting period
// Restrictions:
// - Must be >= [MinConsumptionRate]
// - Must be <= [reward.PercentDenominator]
MaxConsumptionRate uint64 `serialize:"true" json:"maxConsumptionRate"`
// MinValidatorStake is the minimum amount of funds required to become a
// validator.
// Restrictions:
// - Must be > 0
// - Must be <= [InitialSupply]
MinValidatorStake uint64 `serialize:"true" json:"minValidatorStake"`
// MaxValidatorStake is the maximum amount of funds a single validator can
// be allocated, including delegated funds.
// Restrictions:
// - Must be >= [MinValidatorStake]
// - Must be <= [MaximumSupply]
MaxValidatorStake uint64 `serialize:"true" json:"maxValidatorStake"`
// MinStakeDuration is the minimum number of seconds a staker can stake for.
// Restrictions:
// - Must be > 0
MinStakeDuration uint32 `serialize:"true" json:"minStakeDuration"`
// MaxStakeDuration is the maximum number of seconds a staker can stake for.
// Restrictions:
// - Must be >= [MinStakeDuration]
// - Must be <= [GlobalMaxStakeDuration]
MaxStakeDuration uint32 `serialize:"true" json:"maxStakeDuration"`
// MinDelegationFee is the minimum percentage a validator must charge a
// delegator for delegating.
// Restrictions:
// - Must be <= [reward.PercentDenominator]
MinDelegationFee uint32 `serialize:"true" json:"minDelegationFee"`
// MinDelegatorStake is the minimum amount of funds required to become a
// delegator.
// Restrictions:
// - Must be > 0
MinDelegatorStake uint64 `serialize:"true" json:"minDelegatorStake"`
// MaxValidatorWeightFactor is the factor which calculates the maximum
// amount of delegation a validator can receive.
// Note: a value of 1 effectively disables delegation.
// Restrictions:
// - Must be > 0
MaxValidatorWeightFactor byte `serialize:"true" json:"maxValidatorWeightFactor"`
// UptimeRequirement is the minimum percentage a validator must be online
// and responsive to receive a reward.
// Restrictions:
// - Must be <= [reward.PercentDenominator]
UptimeRequirement uint32 `serialize:"true" json:"uptimeRequirement"`
// Authorizes this transformation
SubnetAuth verify.Verifiable `serialize:"true" json:"subnetAuthorization"`
}
AddPermissionlessValidatorTx
type AddPermissionlessValidatorTx struct {
// Metadata, inputs and outputs
BaseTx `serialize:"true"`
// Describes the validator
Validator validator.Validator `serialize:"true" json:"validator"`
// ID of the subnet this validator is validating
Subnet ids.ID `serialize:"true" json:"subnet"`
// Where to send staked tokens when done validating
StakeOuts []*avax.TransferableOutput `serialize:"true" json:"stake"`
// Where to send validation rewards when done validating
ValidatorRewardsOwner fx.Owner `serialize:"true" json:"validationRewardsOwner"`
// Where to send delegation rewards when done validating
DelegatorRewardsOwner fx.Owner `serialize:"true" json:"delegationRewardsOwner"`
// Fee this validator charges delegators as a percentage, times 10,000
// For example, if this validator has DelegationShares=300,000 then they
// take 30% of rewards from delegators
DelegationShares uint32 `serialize:"true" json:"shares"`
}
AddPermissionlessDelegatorTx
type AddPermissionlessDelegatorTx struct {
// Metadata, inputs and outputs
BaseTx `serialize:"true"`
// Describes the validator
Validator validator.Validator `serialize:"true" json:"validator"`
// ID of the subnet this validator is validating
Subnet ids.ID `serialize:"true" json:"subnet"`
// Where to send staked tokens when done validating
Stake []*avax.TransferableOutput `serialize:"true" json:"stake"`
// Where to send staking rewards when done validating
RewardsOwner fx.Owner `serialize:"true" json:"rewardsOwner"`
}
New TypeIDs
ApricotProposalBlock = 0
ApricotAbortBlock = 1
ApricotCommitBlock = 2
ApricotStandardBlock = 3
ApricotAtomicBlock = 4
secp256k1fx.TransferInput = 5
secp256k1fx.MintOutput = 6
secp256k1fx.TransferOutput = 7
secp256k1fx.MintOperation = 8
secp256k1fx.Credential = 9
secp256k1fx.Input = 10
secp256k1fx.OutputOwners = 11
AddValidatorTx = 12
AddSubnetValidatorTx = 13
AddDelegatorTx = 14
CreateChainTx = 15
CreateSubnetTx = 16
ImportTx = 17
ExportTx = 18
AdvanceTimeTx = 19
RewardValidatorTx = 20
stakeable.LockIn = 21
stakeable.LockOut = 22
RemoveSubnetValidatorTx = 23
TransformSubnetTx = 24
AddPermissionlessValidatorTx = 25
AddPermissionlessDelegatorTx = 26
EmptyProofOfPossession = 27
BLSProofOfPossession = 28
BanffProposalBlock = 29
BanffAbortBlock = 30
BanffCommitBlock = 31
BanffStandardBlock = 32