Skip to content
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

added support for txn >5kB #51

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 6 additions & 11 deletions packages/app-btc/src/operations/signTxn/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ export const assertSignTxnParams = (params: ISignTxnParams) => {
assert(params.txn.inputs.length > 0, 'txn.inputs should not be empty');
assert(params.txn.outputs, 'txn.outputs should be defined');
assert(params.txn.outputs.length > 0, 'txn.outputs should not be empty');
assert(params.txn.rawTxn, 'txn.rawTxn should be defined');
assert(params.txn.rawTxn.length > 0, 'txn.rawTxn should not be empty');
assert(
params.txn.inputs.length === params.txn.rawTxn.length,
'txn.rawTxn should not be same length as txn.inputs',
);
Comment on lines +23 to +26
Copy link
Collaborator

Choose a reason for hiding this comment

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

The assert and the error message is conflicting


for (let i = 0; i < params.txn.inputs.length; i += 1) {
const input = params.txn.inputs[i];
Expand All @@ -42,13 +48,6 @@ export const assertSignTxnParams = (params: ISignTxnParams) => {
isHex(input.prevTxnHash),
`txn.inputs[${i}].prevTxnHash should be valid hex string`,
);

if (input.prevTxn) {
assert(
isHex(input.prevTxn),
`txn.inputs[${i}].prevTxn should be valid hex string`,
);
}
}

for (let i = 0; i < params.txn.outputs.length; i += 1) {
Expand All @@ -65,10 +64,6 @@ export const assertSignTxnParams = (params: ISignTxnParams) => {
output.chainIndex,
`txn.outputs[${i}].chainIndex should be define when it's a change output`,
);
assert(
output.addressIndex,
`txn.outputs[${i}].addressIndex should be define when it's a change output`,
);
}
}
};
38 changes: 18 additions & 20 deletions packages/app-btc/src/operations/signTxn/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,52 +62,50 @@ export const signTxn = async (
meta: {
version: signTxnDefaultParams.version,
locktime: params.txn.locktime ?? signTxnDefaultParams.locktime,
inputSize: params.txn.inputs.length,
outputSize: params.txn.inputs.length,
hashType: params.txn.hashType ?? signTxnDefaultParams.hashtype,
inputCount: params.txn.inputs.length,
outputCount: params.txn.outputs.length,
sighash: params.txn.hashType ?? signTxnDefaultParams.hashtype,
},
});
const { metaAccepted } = await helper.waitForResult();
assertOrThrowInvalidResult(metaAccepted);

for (let i = 0; i < params.txn.inputs.length; i += 1) {
const { input: inputRequest } = await helper.waitForResult();
assertOrThrowInvalidResult(inputRequest);
assertOrThrowInvalidResult(inputRequest.index === i);

const input = params.txn.inputs[i];
await helper.sendQuery({
input: {
prevTxn: hexToUint8Array(input.prevTxn),
prevTxnHash: hexToUint8Array(input.prevTxnHash),
prevIndex: input.prevIndex,
prevOutputIndex: input.prevIndex,
scriptPubKey: hexToUint8Array(input.scriptPubKey),
value: input.value,
sequence: input.sequence ?? signTxnDefaultParams.input.sequence,
chainIndex: input.chainIndex,
changeIndex: input.chainIndex,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Rename the params to changeIndex as well

Suggested change
changeIndex: input.chainIndex,
changeIndex: input.changeIndex,

addressIndex: input.addressIndex,
},
});
const { inputAccepted } = await helper.waitForResult();
assertOrThrowInvalidResult(inputAccepted);
}

for (let i = 0; i < params.txn.outputs.length; i += 1) {
const { output: outputRequest } = await helper.waitForResult();
assertOrThrowInvalidResult(outputRequest);
assertOrThrowInvalidResult(outputRequest.index === i);
for (let i = 0; i < params.txn.rawTxn.length; i += 1) {
const txnBytes = hexToUint8Array(params.txn.rawTxn[i]);
await helper.sendInChunks(txnBytes, 'rawTxn', 'rawTxn');
}

for (let i = 0; i < params.txn.outputs.length; i += 1) {
const output = params.txn.outputs[i];
await helper.sendQuery({
output: {
scriptPubKey: hexToUint8Array(output.scriptPubKey),
value: output.value,
isChange: output.isChange,
chainIndex: output.chainIndex,
addressIndex: output.addressIndex,
changesIndex: output.chainIndex,
},
});
const { outputAccepted } = await helper.waitForResult();
assertOrThrowInvalidResult(outputAccepted);
}

const { verified } = await helper.waitForResult();
assertOrThrowInvalidResult(verified);

forceStatusUpdate(SignTxnStatus.SIGN_TXN_STATUS_VERIFY);

const signatures: string[] = [];
Expand All @@ -122,7 +120,7 @@ export const signTxn = async (
const { signature } = await helper.waitForResult();
assertOrThrowInvalidResult(signature);

signatures.push(uint8ArrayToHex(signature.signature));
signatures.push(uint8ArrayToHex(signature.unlockingScript));
Copy link
Collaborator

Choose a reason for hiding this comment

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

Return the signedTxn as well, check eth sign txn

}

forceStatusUpdate(SignTxnStatus.SIGN_TXN_STATUS_CARD);
Expand Down
11 changes: 5 additions & 6 deletions packages/app-btc/src/operations/signTxn/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,18 @@ import { SignTxnStatus } from '../../proto/generated/types';

export type SignTxnEventHandler = (event: SignTxnStatus) => void;

export interface ISignTxnInput {
export interface ISignTxnInputData {
prevTxnHash: string;
prevIndex: number;
value: string;
scriptPubKey: string;

chainIndex: number;
addressIndex: number;

prevTxn: string;
sequence?: number;
}

export interface ISignTxnOutput {
export interface ISignTxnOutputData {
value: string;
scriptPubKey: string;

Expand All @@ -30,8 +28,9 @@ export interface ISignTxnParams {
onEvent?: SignTxnEventHandler;

txn: {
inputs: ISignTxnInput[];
outputs: ISignTxnOutput[];
inputs: ISignTxnInputData[];
outputs: ISignTxnOutputData[];
rawTxn: string[];
Copy link
Collaborator

Choose a reason for hiding this comment

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

We can make this optional and fetch it from server when it's not provided.

locktime?: number;
hashType?: number;
};
Expand Down
56 changes: 56 additions & 0 deletions packages/app-btc/src/utils/operationHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { DeviceAppError, DeviceAppErrorType } from '@cypherock/sdk-interfaces';
import { OnStatus } from '@cypherock/sdk-utils';
import { DeepPartial, Exact, Query, Result } from '../proto/generated/btc/core';
import { assertOrThrowInvalidResult, parseCommonError } from './asserts';
import { ChunkAck, ChunkPayload } from '../proto/generated/common';

export function decodeResult(data: Uint8Array) {
let result: Result;
Expand Down Expand Up @@ -33,6 +34,8 @@ export class OperationHelper<Q extends QueryKey, R extends ResultKey> {

private readonly onStatus?: OnStatus;

private static readonly CHUNK_SIZE = 5120;

constructor(params: {
sdk: ISDK;
queryKey: Q;
Expand Down Expand Up @@ -63,4 +66,57 @@ export class OperationHelper<Q extends QueryKey, R extends ResultKey> {
parseCommonError((result[this.resultKey] as any).commonError);
return resultData;
}

private static splitIntoChunks(txn: Uint8Array): Uint8Array[] {
const chunks: Uint8Array[] = [];
const totalChunks = Math.ceil(txn.length / OperationHelper.CHUNK_SIZE);

for (let i = 0; i < totalChunks; i += 1) {
const chunk = txn.slice(
i * OperationHelper.CHUNK_SIZE,
i * OperationHelper.CHUNK_SIZE + OperationHelper.CHUNK_SIZE,
);
chunks.push(chunk);
}

return chunks;
}

public async sendInChunks<
RK extends keyof Exclude<Result[R], null | undefined>,
QK extends keyof Exclude<Query[Q], null | undefined>,
>(data: Uint8Array, queryKey: QK, resultKey: RK) {
const chunks = OperationHelper.splitIntoChunks(data);
let remainingSize = data.length;

for (let i = 0; i < chunks.length; i += 1) {
const chunk = chunks[i];
remainingSize -= chunk.length;
Comment on lines +69 to +94
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think we need to send in chunks in this PR

Copy link
Contributor Author

Choose a reason for hiding this comment

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

that was part of latest proto, it's split between 2 commits, this commit 8980e19419f43e7cd64a44edac81cc949cbee032 only contains old proto changes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we can open another pr from just that commit if we need to skip chink changes.


const chunkPayload: ChunkPayload = {
chunk,
chunkIndex: i,
totalChunks: chunks.length,
remainingSize,
};

await this.sendQuery({
[queryKey]: {
chunkPayload,
},
});

const result = await this.waitForResult();
assertOrThrowInvalidResult(result[resultKey]);

const { chunkAck } = result[resultKey] as {
chunkAck: ChunkAck;
};

assertOrThrowInvalidResult(chunkAck);
assertOrThrowInvalidResult(
chunkPayload.chunkIndex === chunkAck.chunkIndex,
);
}
}
}
1 change: 1 addition & 0 deletions packages/app-btc/tests/04.signTxn/__fixtures__/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const commonParams = {
sequence: 0xffffffff,
},
],
rawTxn: ['0000'],
outputs: [
{
value: '3547271',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const validParams = {
sequence: 0xffffffff,
},
],
rawTxn: ['0000'],
outputs: [
{
value: '3547271',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const commonParams = {
sequence: 0xffffffff,
},
],
rawTxn: ['0000'],
outputs: [
{
value: '3547271',
Expand Down
Loading