On-Chain Signature Verification & Replay Protection (blaze-v1)
The blaze-v1 contract is the on-chain authority for verifying signed intents within the Blaze protocol. It ensures two critical properties: authenticity (the intent was signed by the claimed user) and uniqueness (the intent cannot be replayed).
The execute Function
When a subnet contract wants to act on a user's signed intent, it calls the blaze-v1.execute public function. This is the primary entry point for verification.
(define-public (execute
(signature (buff 65)) ;; The 65-byte signature from the user
(intent (string-ascii 32)) ;; Intent string (e.g., "TRANSFER_TOKENS")
(opcode (optional (buff 16))) ;; Optional opcode
(amount (optional uint)) ;; Optional amount
(target (optional principal)) ;; Optional target principal
(uuid (string-ascii 36)) ;; The unique UUID for this intent
)
;; ... implementation details ...
)
Key Operations within execute:
-
Replay Protection:
(if (map-insert submitted-uuids uuid true)
;; ... proceed to verification ...
ERR_UUID_SUBMITTED
)The function first attempts to insert the provided
uuidinto thesubmitted-uuidsmap.- If
map-insertreturnstrue, it means the UUID was successfully inserted because it wasn't already present. The intent is considered new, and verification proceeds. - If
map-insertreturnsfalse(because the keyuuidalready exists), it means this intent has been submitted before. The function immediately returnsERR_UUID_SUBMITTED(u409000), preventing replay.
- If
-
Hash Reconstruction: The function reconstructs the 32-byte message hash that the user should have signed. It does this by calling its internal
hashfunction (detailed in "Intents & Signing") usingcontract-calleras thecontractparameter for the hash. This is crucial:blaze-v1assumes thecontractpart of the signed message is the principal of the contract callingexecute(i.e., the subnet contract).(try! (hash contract-caller intent opcode amount target uuid)) -
Signature Verification: The reconstructed hash is then passed to the
verifyfunction along with the user'ssignature.(verify <reconstructed_hash> signature) -
Return Value: If both replay protection and signature verification pass,
executereturns(ok signer-principal), wheresigner-principalis the Stacks principal corresponding to the public key recovered from the signature. If any step fails, an appropriate error is returned.
The verify Function
This internal read-only function performs the cryptographic signature check:
(define-read-only (verify
(message (buff 32)) ;; The 32-byte hash that was supposedly signed
(signature (buff 65)) ;; The user's secp256k1 signature
)
(match (secp256k1-recover? message signature)
public-key (principal-of? public-key) ;; If recovery is successful, get principal from public key
error ERR_INVALID_SIGNATURE ;; If recovery fails
)
)
- It uses the built-in
secp256k1-recover?function to attempt to recover the public key from themessagehash andsignature. - If successful, it converts the recovered
public-keyto a Stacksprincipalusingprincipal-of?and returns(ok recovered-principal). - If
secp256k1-recover?fails (e.g., the signature is invalid for the given message hash), it returnsERR_INVALID_SIGNATURE(u401000).
Other Helper Functions
recover: A read-only version that allows anyone to check a signature against a fully specified intent without attempting to mark the UUID as submitted. Useful for off-chain validation or UI feedback.check: A read-only function to see if auuidhas already been submitted.
By combining these mechanisms, blaze-v1 provides a robust foundation for building secure, intent-driven applications on Stacks.