Implementing a Custom Key
If none of the Key solutions provided by Terra SDK or the community are able to meet your requirements, you might consider writing your own Key implementation.
Here are just a couple that help guide your design pathways:
- Is the private key accessible by developer?
YES: Subclass
terra_sdk.key.raw.RawKey
NO: Subclass
terra_sdk.key.key.Key
- Can the signing agent sign arbitrary data payloads AND use ECDSA on Secp256k1?
YES: Override
Key.sign()
NO: Override
Key.create_signature()
- Can you determine the public key in advance, and is it static?
YES: Call
super()
in constructor with public key to generate addresses & pubkeysNO: Override
acc_address
,val_address
,acc_pubkey
,val_pubkey
properties.
Usually, reasons for requiring a custom Key fall into one of 3 patterns:
External signing
Scenario: The transaction signing is to be performed outside the Python program running Terra SDK, such as signing via hardware wallet (Ledger, Trezor), etc.
Alternative signing algorithm
Scenario: Terra account you need to sign transactions for requires a signature algorithm other than ECDSA on Secp256k1, such as Threshold Multisig or Ed25519.
Customize private key derivation
Scenario: User wants to provide a custom interface for generating a private key, eg. alternative mnemonic schemas, directed key.
The source for MnemonicKey is provided as an example:
from terra_sdk.key.raw import RawKey
from bip32utils import BIP32_HARDEN, BIP32Key
from mnemonic import Mnemonic
class MnemonicKey(RawKey):
def __init__(
self,
mnemonic: str = None,
account: int = 0,
index: int = 0,
coin_type: int = 330,
):
if mnemonic is None:
mnemonic = Mnemonic("english").generate(256)
seed = Mnemonic("english").to_seed(mnemonic)
root = BIP32Key.fromEntropy(seed)
# derive from hdpath
child = (
root.ChildKey(44 + BIP32_HARDEN)
.ChildKey(coin_type + BIP32_HARDEN)
.ChildKey(account + BIP32_HARDEN)
.ChildKey(0)
.ChildKey(index)
)
super().__init__(child.PrivateKey())
self.mnemonic = mnemonic
self.account = account
self.index = index