Truebit Verify
  • Getting Started
    • 📄What is Truebit Verify?
      • How does Truebit work?
      • System Actors
    • ⏱️Get Started
    • ⚙️Architecture
      • Truebit Verify Hub
      • Truebit Verify Nodes
      • What is a transcript?
        • Transcript example
        • API Transcript example
    • Key Concepts
      • What is verification?
      • Determinism
      • WebAssembly
      • Task instrumentation
  • Developing Truebit Tasks
    • Introduction
    • Writing Function Tasks
      • Supported languages
        • Javascript
        • Python
        • Rust
    • Writing API Tasks
    • Task examples
      • Function Task examples
        • Fibonacci
        • Reverse Alphabet
        • Encrypt sha256 using bun.js
        • Encrypt sha256 using Deno
        • ECDSA signature verification
        • NumPy example
      • API Task examples
        • Pet Store CRUD
        • API-Auth examples
    • Namespace management
    • Task Authorization
    • Truebit CLI
      • secret.json
  • Executing Truebit tasks
    • Introduction
    • Task Execution API
      • Execute Function Tasks
      • Execute API Tasks
      • Get Task Status
    • Transcript API
      • Get Transcript
      • Get Invoice
  • Community
    • Truebit Unchained Protocol
    • Support
Powered by GitBook
On this page
  • Description
  • Using Truebit to Execute ECDSA verification example
  • The code
  • Source
  • In/Out parameters
  • Try out
  • Step 1: Create the ecdsa-verify source code
  • Step 2: Build the source code
  • Step 3: Try the code
  • Step 4: Deploy the task

Was this helpful?

  1. Developing Truebit Tasks
  2. Task examples
  3. Function Task examples

ECDSA signature verification

PreviousEncrypt sha256 using DenoNextNumPy example

Last updated 8 days ago

Was this helpful?

Description

This task is an example on how to compute a signature verification using the ECDSA algorithm, the one used in EVM blockchains like Ethereum, Polygon, Hyperledger Besu, Avalanche C-Chain and others. It takes several paramaters as an input, all of them contained in an input.txt file provided as example:

  1. Test string that was signed

  2. Signature with the r, s, v components

  3. Address that signed the message

It will return a boolean indicating if the signature validates correctly

Using Truebit to Execute ECDSA verification example

In order to get a verified result, we can use Truebit to execute the sign-verify task.

The code

You can find the ECDSA signature verification example within the folder truebit-nextgen-examples/function-tasks/js/ecdsa-sign-verify

📁 src └─📄 ecdsa-verify.js 📁 dist └─main.js 📄 package-lock.json 📄 package.json 📄 rollup.config.mjs

The dist folder and the main.js file are going to be generated after running the npx rollup -c command. More information click .

Source

ecdsa-verify.js

/*
    Signee address recoverer and validator
    ======================================
    
    This task is an example on how to compute a signature verification using the ECDSA algorithm, the one used in EVM blockchains like Ethereum, Polygon, Hyperledger Besu, Avalanche C-Chain and others. It takes several paramaters as an input, all of them contained in an input.txt file provided as example: 

    Input parameters (input.txt)
    ----------------------------

        A json-formatted file. See the example below:

            {
                "messageHash": "0x13260446136602c31107aa5e08571c276026b60c5156c1a564e268f3ab08492c",
                "signature": {
                    "r": "0x7097b9a0810d13e60182f261708c2c260e86ea09853cd48b184a5a4b4ea08c02",
                    "s": "0x087bd86b8cdee3aec88ac365ec533c9a111e5b5586c4941a790ca46970c3f380",
                    "v": 28
                },
                "address": "0x63f9a92d8d61b48a9fff8d58080425a3012d05c8"
            }
        
        Fields:

            messageHash: "0x" + hex-encoded data (ASCII string, 66 chars).
            signature: ECDSA signature, divided in its 'r', 's' and 'v'
                       components, as specified below.
                r: "0x" + hex-encoded data (ASCII string, 64 chars).
                s: "0x" + hex-encoded data (ASCII string, 64 chars).
                v: numeric parameter.
            address: "0x" + hex-encoded data (ASCII string, 42 chars).

    Output values (output.txt)
    --------------------------

        A JSON-formatted file. See the example below:

            {
                "declaredAddress": "0x63f9a92d8d61b48a9fff8d58080425a3012d05c8",
                "derivedAddress": "0x63f9a92d8d61b48a9fff8d58080425a3012d05c8",
                "match": true
            }
*/

const fs = require('fs');
const elliptic = require('elliptic');
const keccak256 = require('js-sha3').keccak256;
const bn = require('bn.js');

function checkSignature(messageHash, signature, address) {
    const ec = new elliptic.ec('secp256k1');
    const bnHash = new bn(messageHash, 16);
    const recoveryByteV = signature.v - 27;
    const pubKeyRecovered = ec.recoverPubKey(bnHash, signature, recoveryByteV).encode('hex');
    const pubKeyHash = keccak256(Buffer.from(pubKeyRecovered.slice(2), 'hex'));
    const derivedAddress = pubKeyHash.slice(-40);

    return {
        declaredAddress: '0x' + address,
        derivedAddress: '0x' + derivedAddress,
        match: address === derivedAddress
    }
}

function fixHash(input, key) {
    if (typeof input[key] !== 'string') {
        throw (`invalid type on input key '${key}', not a string.`);
    }
    input[key] = input[key].replace('0x', '').toLowerCase();
}


const main = () => {
    const inputJson = fs.readFileSync('input.txt', 'utf-8');
    let inputObj = JSON.parse(inputJson);

    fixHash(inputObj, 'messageHash');
    fixHash(inputObj.signature, 'r');
    fixHash(inputObj.signature, 's');
    fixHash(inputObj, 'address');

    const outputObj = checkSignature(inputObj.messageHash, inputObj.signature, inputObj.address);
    const outputJson = JSON.stringify(outputObj, null, 4);
    fs.writeFileSync('output.txt', outputJson);
    console.log(outputJson);
}

main();

Recommended configuration for Rollup tool (file rollup.config.mjs):

import nodeResolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import pluginJson from '@rollup/plugin-json';

export default [
    {
        input: 'src/ecdsa-verify.js',
        output: {
            file: 'dist/main.js',
            format: 'es',
            name: 'ecdsa',
        },
        plugins: [
            nodeResolve(),
            commonjs(),
            pluginJson(),
        ],
    }
]

In/Out parameters

In order to send parameters to the Truebit task, you need to open the "input.txt" file and get the value from there. For now, only one input parameter is allowed.

inputJson = fs.readFileSync('input.txt', 'utf-8');

In order to retrieve the output value from the Truebit task, you need save it in the "output.txt" file.

fs.writeFileSync('output.txt', outputJson);

Try out

We will use the Truebit CLI to compile and try our source code. Once the code is finished, we will deploy it to the coordination hub so that everyone who knows the namespace and taskname.

Step 1: Create the ecdsa-verify source code

If you are working in JS, remember to run the Rollup command in order to bundle all the code and dependencies within a single main.js file located at /dist folder.

npx rollup -c

You will find a file called main.js within the folder /dist (This is the file generated by the Rollup tool that will be used for testing purposes)

Step 2: Build the source code

truebit build truebit-nextgen-examples/function-tasks/js/ecdsa-sign-verify/dist -l js

Output

Building the function task
Your function task is ready.
Use the following TaskId for execution or deployment:
js_70f82c303f73ab09ed68dc0fc44829440e8c1838a0b7e0d931dd25e6835be8c2

Step 3: Try the code

In this case, the input parameter is a file containing the address, signature and test data that we want to verify. Please use the file called input.txt located within the root folder.

truebit start js_70f82c303f73ab09ed68dc0fc44829440e8c1838a0b7e0d931dd25e6835be8c2 "$(cat truebit-nextgen-examples/function-tasks/js/ecdsa-sign-verify/input.txt)"

Output

Executing the function Task
Execution Id: 72f88499-efa3-4b8d-be69-cf6f6e3a40a4
Task executed with status: succeed
Task executed with result: true
Task resource usage:
┌───────────────┬───────────────┬───────────────┬───────┬─────────────┬──────────┐
│ (index)       │ Unit          │ Limits        │ Peak  │ Last status │ Capacity │
├───────────────┼───────────────┼───────────────┼───────┼─────────────┼──────────┤
│ Gas           │ 'Steps'       │ 1099511627776 │ 'N/A' │ 16228464673 │ 68       │
│ Nested calls  │ 'Calls'       │ 65536         │ 9336  │ 9304        │ 7        │
│ Frame memory  │ 'Bytes'       │ 524288        │ 29339 │ 27929       │ 18       │
│ System memory │ '64 Kb pages' │ 2048          │ 119   │ '𝚫 1'       │ 17       │
└───────────────┴───────────────┴───────────────┴───────┴─────────────┴──────────┘

Step 4: Deploy the task

truebit deploy <namespace> <taskname> --taskId js_70f82c303f73ab09ed68dc0fc44829440e8c1838a0b7e0d931dd25e6835be8c2

Output

The function task has been deployed successfully.
The Task <taskName> version <version> was registered successfully in namespace <namespace>

Execute the command against Truebit node to get an instrumented Truebit task

Execute the command against the Truebit node to test our Algorithm. You will need to submit the instrumented task id + the input parameter.

Last, but not least, Execute the command to deploy our task to the coordination hub, so that anyone with the namespace, taskname and the can execute it.

API key
here
build
start
deploy