Icon HelpCircleForumIcon Link

⌘K

Icon HelpCircleForumIcon Link
Sway Script With Signature Validation

Icon LinkSway Script With Signature Validation

This guide explains how to work with a Script that rely on in-code signature validation. This is particularly useful when you need to verify that a transaction was authorized by a specific account.

Icon LinkExample Sway Script

Here's an example of a Sway script that validates signatures:

script;
 
use std::{b512::B512, ecr::ec_recover_address, tx::{tx_id, tx_witness_data}};
 
fn main(signer: b256, witness_index: u64) -> bool {
    let witness_data: B512 = tx_witness_data(witness_index).unwrap();
    let address: b256 = ec_recover_address(witness_data, tx_id()).unwrap().bits();
    return address == signer;
}

This script:

  1. Takes 2 parameters; an account address and an witness index
  2. Recovers the entry witness from the transaction's witnesses array using the given index
  3. Validates if the signature was generated by the given account address
  4. Returns true or false based on the validation result

Icon LinkUnderstanding Signature Validation in Fuel

On Fuel, transaction signing involves using a wallet's private key to create a hash based on the transaction ID (which is the same as the transaction hash Icon Link). The transaction ID is generated by hashing the transaction bytes themselves.

Important considerations:

  • Any modification to the transaction after signing will invalidate the signature (modification within the witnesses array do not invalidate the signature)
  • This is because the transaction ID changes when the transaction is modified
  • The signature is typically the last thing added to a transaction, after estimation and funding

Icon LinkSpecial Considerations for Estimation

When working with Sway programs that have in-code signature validation, the estimation process becomes more complex because:

  1. A valid signature is required during the estimation process
  2. The signature must be valid for both during the transaction estimation and later when submitting the transaction
  3. The transaction may be modified during the estimation and funding process, which will result in invalidating any previously added signature

Icon LinkImplementation Example

Here's how to properly implement a transaction with signature validation for this specific Sway script:

// Instantiate the script
const script = new ScriptSigning(signer);
 
/**
 * Witness index in which we will add the signature, since there will only be
 * one witness in this transaction request
 */
const witnessIndex = 0;
 
// Creating the scope invocation to be used later
const request = await script.functions
  .main(signer.address.toB256(), witnessIndex)
  .getTransactionRequest();
 
// Signing the transaction request before estimation
let signature = await signer.signTransaction(request);
 
// Adding the signature to the transaction request
request.addWitness(signature);
 
/**
 * Uses `assembleTx` to estimate and fund the transaction request.
 * Because the transaction only requires enough to cover the fee, there's no
 * need to pass any `accountCoinQuantities` to the `assembleTx` function.
 */
const { assembledRequest } = await provider.assembleTx({
  request,
  feePayerAccount: signer,
});
// Signing the request again as the it was modified during estimation and funding
signature = await signer.signTransaction(assembledRequest);
 
// Updating the signature in the assembled request
assembledRequest.updateWitness(witnessIndex, signature);
 
// Sending the transaction request
const submit = await signer.sendTransaction(assembledRequest);
 
// Getting the result of the transaction
const { isStatusSuccess } = await submit.waitForResult();