Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Generating a Dogecoin address

Dogecoin, like Bitcoin, doesn't use accounts; instead, it uses a UTXO model. A UTXO is a Dogecoin transaction output that is unspent.

Each UTXO is associated with a Dogecoin address that is derived from either a public key or a script that defines the conditions under which the UTXO can be spent. A Dogecoin address is often used as a single-use invoice instead of a persistent address to increase privacy.

Dogecoin P2PKH addresses

Pay-to-public-key-hash (P2PKH) addresses are the most common types of addresses in Dogecoin. On mainnet, they start with the prefix D. They encode the hash of an ECDSA public key.

Dogecoin P2SH addresses

Another type of address is pay-to-script-hash (P2SH) address. It encodes the hash of a Dogecoin script and starts with a A or 9 on mainnet. The script can define complex locking conditions such as multisig or timelocks.

Generating addresses with threshold ECDSA

To generate a Dogecoin address, you need to generate an ECDSA public key. An ECDSA public key can be retrieved using the ecdsa_public_key system API endpoint. The basic Dogecoin example demonstrates how to generate a P2PKH address from a public key:

#[update]
pub async fn get_p2pkh_address() -> String {
    let ctx = DOGE_CONTEXT.with(|ctx| ctx.get());

    // Unique derivation paths are used for every address type generated, to ensure
    // each address has its own unique key pair.
    let derivation_path = DerivationPath::p2pkh(0, 0);

    // Get the ECDSA public key of this smart contract at the given derivation path
    let public_key = get_ecdsa_public_key(&ctx, derivation_path.to_vec_u8_path()).await;

    // Convert the public key to the format used by the Dogecoin library
    let public_key = PublicKey::from_slice(&public_key).unwrap();

    // Generate a P2PKH address from the public key.
    // The address encoding (Base58) depends on the network type.
    Address::p2pkh(public_key, ctx.dogecoin_network).to_string()
}

View the source on GitHub: get_p2pkh_address.rs

/// Retrieves the ECDSA public key for the given derivation path from the ECDSA API.
///
/// This function checks the local in-memory cache first. If no cached key exists,
/// it queries the ECDSA API for the public key at the given derivation path
/// and stores the result in the cache.
pub async fn get_ecdsa_public_key(ctx: &DogecoinContext, derivation_path: Vec<Vec<u8>>) -> Vec<u8> {
    // Check in-memory cache first.
    if let Some(key) = ECDSA_KEY_CACHE.with_borrow(|map| map.get(&derivation_path).cloned()) {
        return key;
    }

    // Request the ECDSA public key from the ECDSA API.
    let public_key = management_canister::ecdsa_public_key(&EcdsaPublicKeyArgs {
        canister_id: None,
        derivation_path: derivation_path.clone(),
        key_id: EcdsaKeyId {
            curve: EcdsaCurve::Secp256k1,
            name: ctx.key_name.to_string(),
        },
    })
    .await
    .unwrap()
    .public_key;

    // Store it in the in-memory cache for future reuse.
    ECDSA_KEY_CACHE.with_borrow_mut(|map| {
        map.insert(derivation_path, public_key.clone());
    });

    public_key
}

View the source on GitHub: ecdsa.rs

Resources

Learn more about Dogecoin P2PKH addresses.

Learn more about the ecdsa_public_key API.