# ECDSA Signature Verification

### 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:&#x20;

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.

### Executing ECDSA Verification Example <a href="#using-bacalhau-to-execute-duckdb-processing" id="using-bacalhau-to-execute-duckdb-processing"></a>

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*

{% tabs %}
{% tab title="Js" %}
📁 src \
└─📄 ecdsa-verify.js\
📁 dist\
└─main.js\
📄 package-lock.json\
📄 package.json\
📄 rollup.config.mjs

{% hint style="info" %}
The ***dist*** folder and the ***main.js*** file are going to be generated after running the `npx rollup -c` command. More information click [here](https://devs.truebit.io/developing-truebit-tasks/supported-languages#development-flow).
{% endhint %}
{% endtab %}
{% endtabs %}

#### Source

{% tabs %}
{% tab title="Js" %}
**ecdsa-verify.js**

{% code overflow="wrap" lineNumbers="true" %}

```javascript
/*
    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();
```

{% endcode %}

Recommended configuration for Rollup tool (file ***rollup.config.mjs***):&#x20;

```javascript
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(),
        ],
    }
]
```

{% endtab %}
{% endtabs %}

#### 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.

{% tabs %}
{% tab title="Js" %}
{% code overflow="wrap" %}

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

{% endcode %}
{% endtab %}
{% endtabs %}

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

{% tabs %}
{% tab title="Js" %}
{% code overflow="wrap" %}

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

{% endcode %}
{% endtab %}
{% endtabs %}

### Trying Out

We will use the [Truebit CLI](https://devs.truebit.io/developing-truebit-tasks/truebit-cli-reference) to [compile](https://devs.truebit.io/developing-truebit-tasks/how-to-create-function-tasks/reverse-alphabet#step-2-build-the-source-code) and [test](https://devs.truebit.io/developing-truebit-tasks/how-to-create-function-tasks/reverse-alphabet#step-3-try-the-code) our source code. Once finalized, we will [deploy](#step-4-deploy-the-task) it to the Coordination Hub so that any user with the `namespace` and `taskname` can access or execute it.

#### Step 1: Create The Ecdsa-Verify Source Code

{% hint style="info" %}
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.&#x20;

`npx rollup -c`
{% endhint %}

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

Execute the [build](https://devs.truebit.io/truebit-cli-reference#build) command against Truebit node to get an instrumented Truebit task.

{% code overflow="wrap" %}

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

{% endcode %}

#### Output

{% code overflow="wrap" %}

```bash
Building the function task
Your function task is ready.
Use the following TaskId for execution or deployment: <taskId>
```

{% endcode %}

#### Step 3: Try The Code

Execute the [start](https://devs.truebit.io/truebit-cli-reference#start) command against the Truebit node to test our Algorithm. You will need to submit the instrumented task id + the input parameter.&#x20;

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.&#x20;

{% code overflow="wrap" %}

```bash
truebit start <taskId> "$(cat truebit-nextgen-examples/function-tasks/js/ecdsa-sign-verify/input.txt)"
```

{% endcode %}

* \[`taskId`]: Add the taskId generated in the previous step.&#x20;

#### Output

{% code fullWidth="false" %}

```bash
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       │
└───────────────┴───────────────┴───────────────┴───────┴─────────────┴──────────┘
```

{% endcode %}

#### Step 4: Deploy The Task

Last, but not least, Execute the [deploy](https://devs.truebit.io/truebit-cli-reference#deploy) command to deploy our task to the coordination hub, so that anyone with the namespace, taskname and the [API key](https://devs.truebit.io/task-authorization#task-authorization-process) can execute it.

<pre class="language-bash" data-overflow="wrap"><code class="lang-bash"><strong>truebit deploy &#x3C;namespace> &#x3C;taskname> --taskId &#x3C;taskId>
</strong></code></pre>

* \[`taskId`]: Add the taskId generated in step 2

#### Output

{% code overflow="wrap" %}

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

{% endcode %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://devs.truebit.io/developing-truebit-tasks/how-to-create-function-tasks/function-task-examples/ecdsa-signature-verification.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
