Skip to content

feat: new SignedData and method argument parser #862

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: feat/nc-args-serialization
Choose a base branch
from

Conversation

r4mmer
Copy link
Member

@r4mmer r4mmer commented May 12, 2025

Motivation

SignedData and RawSignedData

The new SignedData is meant to improve protection, the data should be <signature, value, type>.

In the original SignedData (now called RawSignedData) the oracle signs the value (serialized as the type) to generate the signature.
For the new SignedData the oracle signs the tuple [ncId, value] serialized as Tuple[ContractId, type] to generate the signature.
ncId is the nano contract id being invoked.

The idea is to avoid replay attacks where we get the signed value from one contract to use on another contract.
The serialization itself does not change since the ncId is not part of the data sent, it is only used when generating the signature and when validating it.

MethodArgument parser

There is a distinction from:

  • "user inputs" meant to be used as nano contract arguments
  • Serialized arguments from fullnode API
  • Validated and correctly typed nano contract arguments

Each kind of data should not be treated in the same way, user inputs may not follow the correct typing (due to user errors) so they should be parsed and validated, for this we should use zod.
Fullnode data should also be validated and deserialized into the same type as the user input.

Once the data is valid we can store in a class that makes it easier to (de)serialize and use the data.
To achieve this we need to create a NanoContractMethodArgument class that can be used to (de)serialize arguments to/from the bytes values and from user input with zod validation.

Acceptance Criteria

  • Add NanoContractMethodArgument class to parse and validate arguments
  • Add support for the new SignedData
  • Add support for Tuple fields
  • Prepare support for (de)serializing other container types

Security Checklist

  • Make sure you do not include new dependencies in the project unless strictly necessary and do not include dev-dependencies as production ones. More dependencies increase the possibility of one of them being hijacked and affecting us.

@r4mmer r4mmer self-assigned this May 12, 2025
@r4mmer r4mmer requested a review from pedroferreira1 as a code owner May 12, 2025 18:27
@r4mmer r4mmer moved this from Todo to In Progress (Done) in Hathor Network May 12, 2025
Copy link

codecov bot commented May 13, 2025

Codecov Report

Attention: Patch coverage is 57.22543% with 74 lines in your changes missing coverage. Please review.

Please upload report for BASE (feat/nc-args-serialization@327d6ce). Learn more about missing BASE report.

Files with missing lines Patch % Lines
src/nano_contracts/methodArg.ts 67.81% 28 Missing ⚠️
src/nano_contracts/utils.ts 27.77% 13 Missing ⚠️
src/nano_contracts/deserializer.ts 53.84% 12 Missing ⚠️
src/nano_contracts/serializer.ts 50.00% 11 Missing ⚠️
src/nano_contracts/builder.ts 0.00% 5 Missing ⚠️
src/nano_contracts/parser.ts 0.00% 5 Missing ⚠️

❌ Your patch check has failed because the patch coverage (57.22%) is below the target coverage (70.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@                      Coverage Diff                      @@
##             feat/nc-args-serialization     #862   +/-   ##
=============================================================
  Coverage                              ?   65.87%           
=============================================================
  Files                                 ?       91           
  Lines                                 ?     7068           
  Branches                              ?     1504           
=============================================================
  Hits                                  ?     4656           
  Misses                                ?     2327           
  Partials                              ?       85           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@r4mmer r4mmer moved this from In Progress (Done) to In Progress (WIP) in Hathor Network May 13, 2025
Comment on lines +8 to +9
- feat/nc-args-serialization
- feat/nc-args-class
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These will be removed before merging the PR

Comment on lines +81 to 82
case 'RawSignedData':
case 'SignedData':
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both serialize to the same bytes.
The only difference is that the signature of SignedData also includes the contract id, which is not part of the serialized field.

Comment on lines -266 to +302
toSigned(signedData: Buffer, type: string): DeserializeResult<string> {
const [containerType, internalType] = getContainerInternalType(type);
if (containerType !== 'SignedData') {
throw new Error('Type is not SignedData');
}
if (!internalType) {
throw new Error('Unable to extract type');
}
// Should we check that the valueType is valid?

// SignData[T] is serialized as Serialize(T)+Serialize(sign(T)) where sign() returns a byte str
// Which means we can parse the T argument, then read the bytes after.
toSignedData(signedData: Buffer, type: string): BufferROExtract<NanoContractSignedData> {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type argument changed from being the whole SignedData[innerType] to just the inner type

* Type and value validation for SignedData types.
* returns an instance of NanoContractSignedData
*/
const SignedDataApiInputScheme = z
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is meant to receive the signed data string <signature>,<value>,<type>, validate that value is of type type, signature is a hex string and transform to the internal type NanoContractSignedData

@@ -4,18 +4,94 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { z } from 'zod';
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing the types to be derived from a zod schema was meant to allow parsing and checking the types more easily where needed.

try {
const parsedArgs: NanoContractMethodArgument[] = [];
for (const [index, arg] of methodArgs.entries()) {
const parsedArg = NanoContractMethodArgument.fromApiInput(arg.name, arg.type, args[index]);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fromApiInput parses, validates and converts the data.

@r4mmer r4mmer changed the title feat: method argument value class feat: new SignedData and method argument parser May 15, 2025
@r4mmer r4mmer moved this from In Progress (WIP) to In Progress (Done) in Hathor Network May 15, 2025
@pedroferreira1 pedroferreira1 requested a review from tuliomir May 15, 2025 17:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: In Progress (Done)
Development

Successfully merging this pull request may close these issues.

1 participant