multifactor_test.sol
Overview
The Multifactor contract implements a multi-factor authentication mechanism for secure transaction execution and key management on a blockchain platform. It supports Zero-Knowledge Proof (ZKP) factors, JSON Web Key (JWK) management, security card integration, and controlled transaction submission with confirmation by authorized security cards. The contract enforces strict cryptographic verification, expiration handling, and multi-signature validation to ensure robust security in key updates, transaction authorization, and ownership changes.
Contract: Multifactor
Inherits from Modifiers (imported from ./modifiers/modifiers.sol), which presumably provides access control modifiers such as onlyOwnerPubkey.
Data Structures
Transaction
Represents a queued transaction awaiting confirmation.
Field
Type
Description
iduint64Unique transaction identifier
creatorEphemeral public key (Epk) of the transaction creator
destDestination address of gram transfer
valueuint128Amount of nanograms to transfer
ccmapping(uint32 => varuint32)ECC token amounts to transfer, keyed by token ID
uint16Flags controlling internal message sending behavior
payloadTvmCellMessage body payload for internal outbound message
bounceboolBounce flag for message header
JWKData
Stores modulus bytes and expiration timestamp related to a JWK.
Field
Type
Description
bytesModulus bytes of the JWK
uint64Expiration timestamp of the modulus
Constants
version: Contract version
"1.0.1".WASM module and function identification constants for external TLS data verification.
Various limits such as MAX_QUEUED_REQUESTS,
EXPIRATION_TIME, lifetimes of ephemeral keys and JWKs.Flags for message sending behavior (
FLAG_PAY_FWD_FEE_FROM_BALANCE, FLAG_SEND_ALL_REMAINING).Limits on number of security cards, factors, JWKs, etc.
State Variables
_factors_ordered_by_timestamp: Mapping of composite keys (expiration timestamp and ephemeral public key) to ephemeral public keys, ordered by timestamp to efficiently handle expiration.
_factors_len: Number of active ZKP factors._owner_pubkey: Public key of the master owner (seed phrase).
_candidate_new_owner_pubkey_and_expiration: Optional tuple storing a candidate new owner key and expiration for ownership change requests.
_pub_recovery_key: Public key used for recovery operations._jwk_update_key: Public key authorized to update JWK keys.
_root_provider_certificates: Mapping of root certificate serial numbers to their bytes.
_jwk_modulus_data: Mapping of hashed JWK key IDs to
JWKData._jwk_modulus_data_len: Count of stored JWK modulus entries.
_start_point_jwk: Optional cursor for iterating through JWK data during cleanup._zkid, _index_mod_4,_iss_base_64,_lv_provider_bytes: Strings and bytes storing provider and identity information._use_security_card: Boolean flag indicating if security card functionality is enabled._m_security_cards: Mapping of security card public keys to boolean presence._m_security_cards_len: Count of security cards._m_transactions: Mapping of queued transactions by transaction ID.
_m_transactions_len: Number of queued transactions.
_min_value: Minimum value allowed for transfers._max_cleanup_txns: Maximum number of transactions to clean up in a single batch.
_force_remove_oldest: Flag to force removal of oldest ZKP factor when the max number is reached._verification_key_index: Index used for zero-knowledge proof verification._wasm_hash: Hash of the WASM module used for TLS data verification.
Constructor
Initializes the contract with critical keys, TLS proof, JWK modulus, provider info, and root certificates.
Parameters include various cryptographic keys, signatures, proofs, expiration timestamps, and provider data.
The constructor performs multiple validations:
Non-zero public keys.
Ownership verification.
Signature checks using
tvm.checkSign.Proof verification using
gosh.vergrth16.Timestamp checks for expiration and validity ranges.
Provider length limits.
Sets initial state variables and inserts the first ZKP factor and JWK modulus data.
Key Functions and Methods
ID Generation
generateIdBasedOnTimestampAndUintData(uint64 expire_at, uint256 data_) -> uint256Combines a 64-bit expiration timestamp with the least significant 192 bits of a 256-bit integer to create a composite key for ordered storage.
JWK Management
addJwkModulus(uint256 root_cert_sn, bytes lv_kid, bytes tls_data)Adds or updates a JWK modulus after verifying TLS data via a WASM module. Requires authorization by _jwk_update_key.
Validates the root certificate serial number, TLS data, and expiration timestamp before insertion.
deleteJwkModulusByUpdateJwkKey(bytes kid)Deletes a JWK modulus by key ID. Requires _jwk_update_key authorization.
cleanExpiredJwks(uint8 num_iter)Iteratively deletes expired JWK modulus entries up to num_iter times, using
_start_point_jwkas a cursor.cleanAllExpiredJwks(uint64 epk_expire_at)Cleans all expired JWKs, requires valid ephemeral key authorization.
deleteJwkModulusByFactor(uint64 epk_expire_at, bytes kid)Deletes a JWK modulus entry, authorized by ephemeral key factor.
deleteJwkModulus(bytes kid)Deletes a JWK modulus entry with master owner authorization.
ZKP Factor Management
addZKPfactor(bytes proof, uint256 epk, bytes kid, string header_base_64, uint64 epk_expire_at) -> boolAdds a new ZKP factor after verifying proof correctness and JWK validity.
Cleans expired factors and removes the oldest factor if the max number is reached and
_force_remove_oldestis set.deleteZKPfactorByItself(uint64 epk_expire_at)Allows a ZKP factor to delete itself by providing its expiration timestamp.
cleanExpiredZKPFactors(uint8 num_iter)Removes expired ZKP factors iteratively.
cleanOldestZKPFactor()Removes the oldest ZKP factor from storage.
cleanAllExpiredZKPFactors(uint64 epk_expire_at)Cleans all expired ZKP factors authorized by ephemeral key.
deleteZKPfactor(uint64 epk_expire_at, uint256 epk)Deletes a specific ZKP factor by master owner.
deleteZKPfactor_(uint256 epk)Deletes a ZKP factor by ephemeral key value (internal search).
Ownership and Key Updates
updateRecoveryPhrase(uint256 new_pub_recovery_key, bytes new_pub_recovery_key_sig)Updates the recovery key with signature validation by master owner.
updateJwkUpdateKey(uint256 new_jwk_update_key, bytes new_jwk_update_key_sig)Updates the JWK update key.
Updates the ZK identity (
_zkid), provider certificates, and resets keys and factors. Requires master owner authorization and extensive validation similar to constructor.updateSeedPhrase(uint256 new_owner_pubkey, bytes new_owner_pubkey_sig)Updates the master owner public key (seed phrase).
changeSeedPhrase(uint64 epk_expire_at, uint256 new_owner_pubkey, bytes new_owner_pubkey_sig)Initiates a multi-factor authenticated ownership change by proposing a new owner key. The request is stored as a candidate.
acceptCandidateSeedPhrase(uint256 new_owner_pubkey)Recovery key approves the candidate new owner key, completing ownership transfer.
deleteCandidateSeedPhrase(uint64 epk_expire_at)Cancels the pending ownership change request.
Security Card Management
addSecurityCard(uint256 pubkey, bytes pubkey_sig)Adds a new security card key with signature verification.
turnOffSecurityCards()Disables security card usage.
turnOnSecurityCards()Enables security card usage if at least one card exists.
deleteSecurityCard(uint256 pubkey)Removes a security card by public key.
deleteAllSecurityCards()Removes all security cards and disables the feature.
Transaction Management
sendTransaction(uint64 epk_expire_at, address dest, uint128 value, mapping(uint32 => varuint32) cc, bool bounce, uint8 flags, TvmCell payload) -> addressDirectly sends a transaction to the destination if security card functionality is disabled.
Requires ephemeral factor authorization and minimum value check.
submitTransaction(uint64 epk_expire_at, address dest, uint128 value, mapping(uint32 => varuint32) cc, bool bounce, bool allBalance, TvmCell payload) -> uint64Submits a transaction to be queued for confirmation by security cards if enabled.
If security cards are off, sends the transaction immediately.
confirmTransaction(uint64 transactionId)Security card holders confirm queued transactions, triggering transfer execution.
removeExpiredTransactions()Internal function to purge expired transactions based on a timestamp boundary. Limits cleanup to _max_cleanup_txns per call.
Token Exchange
exchangeToken(uint64 epk_expire_at, uint64 value)Allows ephemeral key holders to exchange tokens (calls external
gosh.cnvrtshellq).exchangeTokenWithOwner(uint64 value)Allows master owner to exchange tokens.
Auxiliary Setters
setMaxCleanupTxns(uint64 epk_expire_at, uint value)Set maximum cleanup transactions per batch.
setMinValue(uint64 epk_expire_at, uint128 value)Set minimum transfer value.
setWasmHash(bytes wasm_hash)Update the WASM hash used for TLS verification.
setForceRemoveOldest(bool flag)Enable or disable forced removal of oldest ZKP factor when max reached.
Getters
getTransaction(uint64 transactionId) -> TransactionRetrieves transaction details by ID.
getTransactions() -> Transaction[]Returns all pending, non-expired transactions.
getTransactionIds() -> uint64[]Returns IDs of all queued transactions.
getZKPEphemeralPublicKeys() -> uint256[]Returns all active ephemeral public keys (ZKP factors).
getTimeStamp() -> uint32Returns current block timestamp.
getSecurityCardKeys() -> uint256[]Returns all security card public keys.
get_epk_expire_at(uint256 epk) -> uint64Returns the expiration timestamp of a given ephemeral public key.
getVersion() -> (string, string)Returns contract version and name.
Important Implementation Details
Composite Key Design for Ordered Mappings
The contract uses composite keys combining expiration timestamps (64 bits) and ephemeral public key data (192 bits) for ordered mappings (_factors_ordered_by_timestamp). This design enables efficient expiration cleanup by iterating from the oldest timestamp.
Zero-Knowledge Proof Verification
Functions that add ZKP factors or update identities require verification of cryptographic proofs by calling
gosh.vergrth16with Poseidon hash inputs, ensuring proof validity linked to the contract's state.WASM Module Integration for TLS Data Verification
The contract leverages an external WASM module (tlschecker) to verify TLS-related data for JWK modulus additions, ensuring that JWK data is authenticated before acceptance.
Multi-Factor Authentication
Critical operations require ephemeral keys validated by proofs and/or signatures, ensuring multi-factor security beyond a single key.
Security Card Confirmation Workflow
When security cards are enabled, transactions are queued and require confirmation by an authorized security card public key before execution, adding a second layer of approval.
Expiration and Cleanup Mechanisms
Both ZKP factors and queued transactions have expiration times. The contract includes functions to clean expired entries regularly to maintain storage size and security.
Multi-Stage Ownership Change
The contract supports a two-step ownership change process, involving a candidate key proposed by an ephemeral factor and final acceptance by the recovery key, mitigating unauthorized ownership changes.
Interaction with Other Parts of the System
ModifiersContractProvides access control mechanisms such as onlyOwnerPubkey.
gosh Library or Object
Used extensively for cryptographic functions:
poseidonfor hashing.vergrth16for zero-knowledge proof verification.cnvrtshellqfor token exchange.runwasmconcatmultiarg to execute the external WASM module for TLS verification.
tvm Environment
For signature checks (
tvm.checkSign), message acceptance (tvm.accept), and blockchain time (block.timestamp).
Usage Examples
Adding a ZKP Factor
bool success = multifactor.addZKPfactor(
proofData,
ephemeralPubKey,
kidBytes,
headerBase64,
epkExpireAt
);
Adds a new zero-knowledge proof factor after validating the proof, JWK presence, and expiration constraints.
Submitting a Transaction with Security Cards Enabled
uint64 txnId = multifactor.submitTransaction(
epkExpireAt,
destinationAddress,
valueInNanoGrams,
ccMapping,
bounceFlag,
allBalanceFlag,
payloadCell
);
// Transaction is queued and requires confirmation by a security card.
Confirming a Queued Transaction
multifactor.confirmTransaction(transactionId);
Called by an authorized security card public key to execute the queued transaction.
Mermaid Diagram
classDiagram
class Multifactor {
+Transaction struct
+JWKData struct
+constructor()
+addJwkModulus()
+deleteJwkModulusByUpdateJwkKey()
+cleanExpiredJwks()
+addZKPfactor()
+deleteZKPfactorByItself()
+cleanExpiredZKPFactors()
+deleteZKPfactor()
+changeSeedPhrase()
+acceptCandidateSeedPhrase()
+addSecurityCard()
+turnOffSecurityCards()
+turnOnSecurityCards()
+deleteSecurityCard()
+sendTransaction()
+submitTransaction()
+confirmTransaction()
+removeExpiredTransactions()
+exchangeToken()
+setMaxCleanupTxns()
+setMinValue()
+getTransaction()
+getTransactions()
+getZKPEphemeralPublicKeys()
+getSecurityCardKeys()
}
Multifactor --> Modifiers