-
Notifications
You must be signed in to change notification settings - Fork 15
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
base: feat/nc-args-serialization
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
❌ 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. 🚀 New features to boost your workflow:
|
- feat/nc-args-serialization | ||
- feat/nc-args-class |
There was a problem hiding this comment.
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
case 'RawSignedData': | ||
case 'SignedData': |
There was a problem hiding this comment.
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.
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> { |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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'; |
There was a problem hiding this comment.
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]); |
There was a problem hiding this comment.
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.
Motivation
SignedData and RawSignedData
The new
SignedData
is meant to improve protection, the data should be<signature, value, type>
.In the original
SignedData
(now calledRawSignedData
) 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 asTuple[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:
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
Security Checklist