Skip to main content

Module 0x3::validator_cap

use 0x2::object;
use 0x2::transfer;
use 0x2::tx_context;

Resource UnverifiedValidatorOperationCap

The capability object is created when creating a new Validator or when the validator explicitly creates a new capability object for rotation/revocation. The holder address of this object can perform some validator operations on behalf of the authorizer validator. Thus, if a validator wants to separate the keys for operation (such as reference gas price setting or tallying rule reporting) from fund/staking, it could transfer this capability object to another address. To facilitate rotating/revocation, Validator stores the ID of currently valid UnverifiedValidatorOperationCap. Thus, before converting UnverifiedValidatorOperationCap to ValidatorOperationCap, verification needs to be done to make sure the cap object is still valid.

struct UnverifiedValidatorOperationCap has store, key
id: object::UID
authorizer_validator_address: address

Struct ValidatorOperationCap

Privileged operations require ValidatorOperationCap for permission check. This is only constructed after successful verification.

struct ValidatorOperationCap has drop
authorizer_validator_address: address

Function unverified_operation_cap_address

public(friend) fun unverified_operation_cap_address(cap: &validator_cap::UnverifiedValidatorOperationCap): &address
public(package) fun unverified_operation_cap_address(cap: &UnverifiedValidatorOperationCap): &address {

Function verified_operation_cap_address

public(friend) fun verified_operation_cap_address(cap: &validator_cap::ValidatorOperationCap): &address
public(package) fun verified_operation_cap_address(cap: &ValidatorOperationCap): &address {

Function new_unverified_validator_operation_cap_and_transfer

Should be only called by the friend modules when adding a Validator or rotating an existing validaotr's operation_cap_id.

public(friend) fun new_unverified_validator_operation_cap_and_transfer(validator_address: address, ctx: &mut tx_context::TxContext): object::ID
public(package) fun new_unverified_validator_operation_cap_and_transfer(
    validator_address: address,
    ctx: &mut TxContext,
): ID {
    // This function needs to be called only by the validator itself, except
    // 1. in genesis where all valdiators are created by @0x0
    // 2. in tests where @0x0 could be used to simplify the setup
    let sender_address = ctx.sender();
    assert!(sender_address == @0x0 || sender_address == validator_address, 0);

    let operation_cap = UnverifiedValidatorOperationCap {
        id: object::new(ctx),
        authorizer_validator_address: validator_address,
    let operation_cap_id = object::id(&operation_cap);
    transfer::public_transfer(operation_cap, validator_address);

Function new_from_unverified

Convert an UnverifiedValidatorOperationCap to ValidatorOperationCap. Should only be called by validator_set module AFTER verification.

public(friend) fun new_from_unverified(cap: &validator_cap::UnverifiedValidatorOperationCap): validator_cap::ValidatorOperationCap
public(package) fun new_from_unverified(
    cap: &UnverifiedValidatorOperationCap,
): ValidatorOperationCap {
    ValidatorOperationCap {
        authorizer_validator_address: cap.authorizer_validator_address