Skip to content

Latest commit

 

History

History
402 lines (233 loc) · 16.1 KB

SharedEd25519PublicKey.md

File metadata and controls

402 lines (233 loc) · 16.1 KB

Module 0x1::SharedEd25519PublicKey

Each address that holds a SharedEd25519PublicKey resource can rotate the public key stored in this resource, but the account's authentication key will be updated in lockstep. This ensures that the two keys always stay in sync.

Resource SharedEd25519PublicKey

A resource that forces the account associated with rotation_cap to use a ed25519 authentication key derived from key

resource struct SharedEd25519PublicKey
Fields
key: vector<u8>
32 byte ed25519 public key
rotation_cap: DiemAccount::KeyRotationCapability
rotation capability for an account whose authentication key is always derived from key

Constants

The shared ed25519 public key is not valid ed25519 public key

const EMALFORMED_PUBLIC_KEY: u64 = 0;

A shared ed25519 public key resource was not in the required state

const ESHARED_KEY: u64 = 1;

Function publish

(1) Rotate the authentication key of the sender to key (2) Publish a resource containing a 32-byte ed25519 public key and the rotation capability of the sender under the account's address. Aborts if the sender already has a SharedEd25519PublicKey resource. Aborts if the length of new_public_key is not 32.

public fun publish(account: &signer, key: vector<u8>)
Implementation
public fun publish(account: &signer, key: vector<u8>) {
    let t = SharedEd25519PublicKey {
        key: x"",
        rotation_cap: DiemAccount::extract_key_rotation_capability(account)
    };
    rotate_key_(&mut t, key);
    assert(!exists_at(Signer::address_of(account)), Errors::already_published(ESHARED_KEY));
    move_to(account, t);
}
Specification
include PublishAbortsIf;
include PublishEnsures;

schema PublishAbortsIf {
    account: signer;
    key: vector<u8>;
    
    let addr = Signer::spec_address_of(account);
    include DiemAccount::ExtractKeyRotationCapabilityAbortsIf;
    include RotateKey_AbortsIf {
            shared_key: SharedEd25519PublicKey {
                key: x"",
                rotation_cap: DiemAccount::spec_get_key_rotation_cap(addr)
            },
            new_public_key: key
    };
    aborts_if exists_at(addr) with Errors::ALREADY_PUBLISHED;
}

schema PublishEnsures {
    account: signer;
    key: vector<u8>;
    
    let addr = Signer::spec_address_of(account);
    ensures exists_at(addr);
    include RotateKey_Ensures { shared_key: global<SharedEd25519PublicKey>(addr), new_public_key: key};
}

Function rotate_key_

fun rotate_key_(shared_key: &mut SharedEd25519PublicKey::SharedEd25519PublicKey, new_public_key: vector<u8>)
Implementation
fun rotate_key_(shared_key: &mut SharedEd25519PublicKey, new_public_key: vector<u8>) {
    // Cryptographic check of public key validity
    assert(
        Signature::ed25519_validate_pubkey(copy new_public_key),
        Errors::invalid_argument(EMALFORMED_PUBLIC_KEY)
    );
    DiemAccount::rotate_authentication_key(
        &shared_key.rotation_cap,
        Authenticator::ed25519_authentication_key(copy new_public_key)
    );
    shared_key.key = new_public_key;
}
Specification

schema RotateKey_AbortsIf {
    shared_key: SharedEd25519PublicKey;
    new_public_key: vector<u8>;
    aborts_if !Signature::ed25519_validate_pubkey(new_public_key) with Errors::INVALID_ARGUMENT;
    include DiemAccount::RotateAuthenticationKeyAbortsIf {
        cap: shared_key.rotation_cap,
        new_authentication_key: Authenticator::spec_ed25519_authentication_key(new_public_key)
    };
}

schema RotateKey_Ensures {
    shared_key: SharedEd25519PublicKey;
    new_public_key: vector<u8>;
    ensures shared_key.key == new_public_key;
}

Function rotate_key

(1) rotate the public key stored account's SharedEd25519PublicKey resource to new_public_key (2) rotate the authentication key using the capability stored in the account's SharedEd25519PublicKey to a new value derived from new_public_key Aborts if the sender does not have a SharedEd25519PublicKey resource. Aborts if the length of new_public_key is not 32.

public fun rotate_key(account: &signer, new_public_key: vector<u8>)
Implementation
public fun rotate_key(account: &signer, new_public_key: vector<u8>) acquires SharedEd25519PublicKey {
    let addr = Signer::address_of(account);
    assert(exists_at(addr), Errors::not_published(ESHARED_KEY));
    rotate_key_(borrow_global_mut<SharedEd25519PublicKey>(addr), new_public_key);
}
Specification

schema RotateKeyAbortsIf {
    account: signer;
    new_public_key: vector<u8>;
    
    let addr = Signer::spec_address_of(account);
    aborts_if !exists_at(addr) with Errors::NOT_PUBLISHED;
    include RotateKey_AbortsIf {shared_key: global<SharedEd25519PublicKey>(addr)};
}

schema RotateKeyEnsures {
    account: signer;
    new_public_key: vector<u8>;
    
    let addr = Signer::spec_address_of(account);
    include RotateKey_Ensures {shared_key: global<SharedEd25519PublicKey>(addr)};
}

Function key

Return the public key stored under addr. Aborts if addr does not hold a SharedEd25519PublicKey resource.

public fun key(addr: address): vector<u8>
Implementation
public fun key(addr: address): vector<u8> acquires SharedEd25519PublicKey {
    assert(exists_at(addr), Errors::not_published(ESHARED_KEY));
    *&borrow_global<SharedEd25519PublicKey>(addr).key
}

Function exists_at

Returns true if addr holds a SharedEd25519PublicKey resource.

public fun exists_at(addr: address): bool
Implementation
public fun exists_at(addr: address): bool {
    exists<SharedEd25519PublicKey>(addr)
}

Module Specification

Persistence

invariant update [global] forall addr: address where old(exists<SharedEd25519PublicKey>(addr)):
    exists<SharedEd25519PublicKey>(addr);