-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #67 from proto-kit/feature/tx-validation
Implement basic version of tx validation
- Loading branch information
Showing
3 changed files
with
83 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
packages/sequencer/src/mempool/verification/TransactionValidator.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { inject, injectable } from "tsyringe"; | ||
import { | ||
MethodIdResolver, | ||
MethodParameterDecoder, | ||
Runtime, | ||
RuntimeModulesRecord, | ||
} from "@proto-kit/module"; | ||
|
||
import { PendingTransaction } from "../PendingTransaction"; | ||
|
||
@injectable() | ||
export class TransactionValidator { | ||
public constructor( | ||
@inject("Runtime") private readonly runtime: Runtime<RuntimeModulesRecord>, | ||
@inject("MethodIdResolver") | ||
private readonly methodIdResolver: MethodIdResolver | ||
) {} | ||
|
||
private validateMethod(tx: PendingTransaction): string | undefined { | ||
// Check if method exists | ||
|
||
// We don't actually need to use runtime.getMethodById here, bcs the | ||
// module name validation happens inside getMethodNameFromId | ||
// and also in the next step | ||
const methodPath = this.methodIdResolver.getMethodNameFromId( | ||
tx.methodId.toBigInt() | ||
); | ||
|
||
if (methodPath === undefined) { | ||
return `Method with id ${tx.methodId} does not exist`; | ||
} | ||
|
||
// Check if parameters are decodable | ||
const runtimeModule = this.runtime.resolve(methodPath[0]); | ||
const decoder = MethodParameterDecoder.fromMethod( | ||
runtimeModule, | ||
methodPath[1] | ||
); | ||
|
||
// We don't do additional checks for args yet - so the only thing we | ||
// can check is if the Field[]'s length matches | ||
if (tx.args.length !== decoder.fieldSize) { | ||
return "Arguments field length doesn't match required length"; | ||
} | ||
return undefined; | ||
} | ||
|
||
public validateTx(tx: PendingTransaction): [boolean, string | undefined] { | ||
const methodError = this.validateMethod(tx); | ||
|
||
if (methodError !== undefined) { | ||
return [false, methodError]; | ||
} | ||
|
||
const validSignature = tx.signature.verify( | ||
tx.sender, | ||
tx.getSignatureData() | ||
); | ||
|
||
if (!validSignature.toBoolean()) { | ||
return [false, "Signature provided is not valid"]; | ||
} | ||
|
||
return [true, undefined]; | ||
} | ||
} |