This doc goes into the required features for an SDK, and what they should support.
It should support serialization and deserialization of:
- unsigned integers u8, u16, u32, u64, u128, u256
- signed integers i8, i16, i32, i64, i128, i256
- booleans bool
- vectors
- tuples
- fixed length vectors (and addresses)
Serialization should be provided as the native way for the language of the SDK. More details of the specification can be found here
Transactions should be able to be signed and authorized with the following key types:
- Ed25519 (standalone) -
TransactionAuthenticator::Ed25519(variant 0) - MultiEd25519 -
TransactionAuthenticator::MultiEd25519(variant 1) - Ed25519 (Single Key) -
TransactionAuthenticator::SingleSender>AccountAuthenticator::SingleKey>AnyPublicKey::Ed25519(variant 0) - Secp256k1 (Single Key) -
TransactionAuthenticator::SingleSender>AccountAuthenticator::SingleKey>AnyPublicKey::Secp256k1Ecdsa(variant 1) - Secp256r1 (Single Key) -
TransactionAuthenticator::SingleSender>AccountAuthenticator::SingleKey>AnyPublicKey::Secp256r1Ecdsa(variant 2) - MultiKey -
TransactionAuthenticator::SingleSender>AccountAuthenticator::MultiKey(variant 3) - (Optional) Keyless -
TransactionAuthenticator::SingleSender>AccountAuthenticator::SingleKey>AnyPublicKey::Keyless(variant 3)
-
Build a
RawTransactionwith BCS serialization:RawTransaction { sender: AccountAddress (32 bytes) sequence_number: u64 (little-endian) payload: TransactionPayload (enum) max_gas_amount: u64 (little-endian) gas_unit_price: u64 (little-endian) expiration_timestamp_secs: u64 (little-endian) chain_id: ChainId (1 byte) } -
Create signing message:
signing_message = SHA3-256_prefix || BCS(RawTransaction)- The prefix is:
b5e97db07fa0bd0e5598aa3643a9bc6f6693bddc1a9fec9e674a461eaa00b193(SHA3-256 of "APTOS::RawTransaction")
- The prefix is:
-
Sign the signing message with the appropriate key type
-
Create
SignedTransaction=RawTransaction + TransactionAuthenticator
| Variant | Index | Description |
|---|---|---|
| Ed25519 | 0 | Single Ed25519 signature (97 bytes: 1 + 32 + 64) |
| MultiEd25519 | 1 | K-of-N Ed25519 multisig |
| MultiAgent | 2 | Multiple independent signers |
| FeePayer | 3 | Sponsored transaction |
| SingleSender | 4 | Modern unified format (recommended) |
| Variant | Index | Description |
|---|---|---|
| Ed25519 | 0 | Legacy Ed25519 |
| MultiEd25519 | 1 | Legacy multi-Ed25519 |
| SingleKey | 2 | Modern single-key (supports multiple algorithms) |
| MultiKey | 3 | Modern multi-key (supports heterogeneous keys) |
| NoAccountAuthenticator | 4 | No authentication |
| Abstract | 5 | Abstract authentication |
| Variant | Index | Key Size |
|---|---|---|
| Ed25519 | 0 | 32 bytes |
| Secp256k1Ecdsa | 1 | 65 bytes (uncompressed) |
| Secp256r1Ecdsa | 2 | 65 bytes (uncompressed) |
| Keyless | 3 | Variable |
| FederatedKeyless | 4 | Variable |
| Variant | Index | Signature Size |
|---|---|---|
| Ed25519 | 0 | 64 bytes |
| Secp256k1Ecdsa | 1 | 64 bytes (r || s) |
| WebAuthn | 2 | Variable |
| Keyless | 3 | Variable |
Authentication keys must be able to be created for accounts that use:
- Ed25519 (standalone):
auth_key = SHA3-256(public_key || 0x00)(scheme_id = 0) - MultiEd25519:
auth_key = SHA3-256(serialized_multi_public_key || 0x01)(scheme_id = 1) - Ed25519 (Single Key):
auth_key = SHA3-256(BCS(AnyPublicKey::Ed25519) || 0x02)(scheme_id = 2) - Secp256k1 (Single Key):
auth_key = SHA3-256(BCS(AnyPublicKey::Secp256k1) || 0x02)(scheme_id = 2) - Secp256r1 (Single Key):
auth_key = SHA3-256(BCS(AnyPublicKey::Secp256r1) || 0x02)(scheme_id = 2) - MultiKey:
auth_key = SHA3-256(BCS(MultiKey) || 0x03)(scheme_id = 3) - (Optional) Keyless:
auth_key = SHA3-256(BCS(AnyPublicKey::Keyless) || 0x02)(scheme_id = 2)
Important: The same key using different authenticator formats (e.g., Ed25519 standalone vs SingleKey(Ed25519)) will produce different addresses due to different scheme IDs.
-
For SingleKey authentication,
BCS(AnyPublicKey)includes the variant index:- Ed25519:
0x00 || public_key_bytes (32 bytes) - Secp256k1:
0x01 || public_key_bytes (65 bytes) - Secp256r1:
0x02 || public_key_bytes (65 bytes)
- Ed25519:
-
For MultiKey authentication:
MultiKey { public_keys: Vec<AnyPublicKey> // ULEB128 length + each serialized AnyPublicKey signatures_required: u8 } -
For MultiEd25519 (legacy format, no length prefix):
public_key_bytes = pk0 (32) || pk1 (32) || ... || pkN (32) || threshold (1)
Must support the following key types
- Ed25519 - 32-byte public key, 64-byte signature (EdDSA over Curve25519)
- Secp256k1 - 65-byte uncompressed public key (04 || x || y), 64-byte signature (r || s)
- Secp256r1 - 65-byte uncompressed public key (04 || x || y), WebAuthn signatures
All keys must support reading and outputting in AIP-80 format.
Transactions must be able to use the following replay protectors (not at the same time)
- Sequence Number - u64 field in RawTransaction, must equal on-chain sequence number
- Orderless (hash for 60s)
Transactions also must support the following types:
- Standard (Single sender) - Uses
TransactionAuthenticator::Ed25519orTransactionAuthenticator::SingleSender - Multiagent - Uses
TransactionAuthenticator::MultiAgent(variant 2) - Multisig - Uses
TransactionPayload::Multisig(variant 3) - Fee Payer (Sponsored) - Uses
TransactionAuthenticator::FeePayer(variant 3) - Multiagent fee payer - Combines MultiAgent and FeePayer patterns
| Variant | Index | Description |
|---|---|---|
| Script | 0 | Execute a Move script |
| ModuleBundle | 1 | Deprecated - Do not use |
| EntryFunction | 2 | Call an entry function (most common) |
| Multisig | 3 | Execute via multisig account |
EntryFunction {
module: ModuleId {
address: AccountAddress (32 bytes)
name: Identifier (ULEB128 length + UTF-8 bytes)
}
function: Identifier (ULEB128 length + UTF-8 bytes)
ty_args: Vec<TypeTag> (ULEB128 length + each TypeTag)
args: Vec<Vec<u8>> (ULEB128 length + each BCS-encoded argument)
}
MultiEd25519Signature {
signatures: sig0 (64) || sig1 (64) || ... || sigM (64) // No length prefix
bitmap: 4 bytes (bits indicate which keys signed, MSB first per byte)
}
MultiKeyAuthenticator {
public_keys: MultiKey {
public_keys: Vec<AnyPublicKey>
signatures_required: u8
}
signatures: Vec<AnySignature> // Ordered by key index
signatures_bitmap: BitVec {
num_bits: u16 (little-endian)
bytes: Vec<u8> // Packed bits, bit 0 = MSB of first byte
}
}
Transactions are signed by BCS serializing the transaction payload.
Must support account addresses that are
- Parsable from string (hex format with or without 0x prefix)
- Outputs in AIP-40 format (LONG format: 64 hex characters with 0x prefix, lowercase, no trimming of leading zeros)
- Fixed 32 bytes (256 bits)
- Derived from the authentication key (which is the full 32-byte SHA3-256 hash)
- Special addresses:
0x1(framework),0x0(VM), etc. should be left-padded with zeros