Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
9 changes: 9 additions & 0 deletions .changeset/wise-candies-stop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@offckb/cli': minor
---

Replace ckb-transaction-dumper with ccc-based implementation

- Rewrite transaction dumper to use ccc Client and molecule codecs
- Implement dep_group unpacking using ccc.mol
- Remove ckb-transaction-dumper npm dependency
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ package-lock.json
# Test coverage
coverage/
*.lcov

# Sisyphus plans and sessions
.sisyphus/
175 changes: 175 additions & 0 deletions .sisyphus/plans/ckb-tx-dumper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
# Replace ckb-transaction-dumper with ccc-based implementation

## TL;DR

> **Quick Summary**: Replace `ckb-transaction-dumper` npm package with a pure ccc-based implementation.
>
> **Deliverables**:
>
> - New `src/tools/ckb-tx-dumper.ts` (replaces old implementation)
> - Removed `ckb-transaction-dumper` from package.json
>
> **Estimated Effort**: Medium (2-3 hours)
> **Parallel Execution**: NO - sequential

---

## Context

### Request

Replace `ckb-transaction-dumper` with ccc-based implementation (no external dependencies, use ccc throughout).

### Current Implementation

- `src/tools/ckb-tx-dumper.ts` spawns `ckb-transaction-dumper` binary
- Depends on npm package `ckb-transaction-dumper@0.4.2`

### What TransactionDumper Does

1. Load transaction (from file or fetch by hash)
2. Resolve cell deps (handle dep_group type)
3. Resolve inputs
4. Output mock transaction JSON for ckb-debugger

### ccc Molecule Support

ccc provides full molecule codec:

- `ccc.molecule.struct()` - for OutPoint { tx_hash, index }
- `ccc.molecule.vector()` - for OutPointVec
- `ccc.Byte32`, `ccc.Uint32LE` - predefined codecs

No manual bytes parsing needed!

---

## Work Objectives

### Core Objective

Replace `ckb-transaction-dumper` with pure ccc implementation.

### Must Have

- Keep `DumpOption` interface
- Keep `dumpTransaction()` signature
- Same JSON output format

### Must NOT Have

- Breaking API changes
- New dependencies

---

## TODOs

- [ ] 1. Implement ccc-based transaction dumper

**What to do**:

- Rewrite `src/tools/ckb-tx-dumper.ts`
- Use ccc Client for RPC calls
- Use ccc molecule codecs for dep_group unpacking

**Key implementation**:

```typescript
import { ccc } from '@ckb-ccc/core';

// OutPoint codec for dep_group unpacking
const OutPointCodec = ccc.molecule.struct({
txHash: ccc.Byte32,
index: ccc.Uint32LE,
});

const OutPointVecCodec = ccc.molecule.vector(OutPointCodec);

// Unpack dep_group data
function unpackDepGroup(data: string): ccc.OutPoint[] {
return OutPointVecCodec.decode(data).map((o) =>
ccc.OutPoint.from({ txHash: o.txHash, index: '0x' + o.index.toString(16) }),
);
}
```

**Acceptance Criteria**:

- [ ] Uses ccc Client for RPC
- [ ] Uses ccc molecule for dep_group
- [ ] Same output format

**QA Scenarios**:

```
Scenario: Compiles successfully
Tool: Bash
Steps: npm run typecheck
Expected: No errors
```

**Commit**: `feat: implement transaction dumper with ccc`

---

- [ ] 2. Remove ckb-transaction-dumper dependency

**What to do**:

- Remove from `package.json`
- Run `pnpm install`

**Commit**: `chore: remove ckb-transaction-dumper`

---

## Verification

```bash
npm run typecheck
npm run lint
grep -c "ckb-transaction-dumper" package.json || echo "Clean"
```

## Key Implementation Notes

### Dep Group Unpacking with ccc

```typescript
const OutPointCodec = ccc.molecule.struct({
txHash: ccc.Byte32,
index: ccc.Uint32LE,
});
const OutPointVecCodec = ccc.molecule.vector(OutPointCodec);

// Usage
const outpoints = OutPointVecCodec.decode(cellData);
```

### Mock Transaction Structure

```typescript
interface MockTransaction {
mock_info: {
inputs: MockInput[];
cell_deps: MockCellDep[];
header_deps: any[];
};
tx: Transaction;
}
```

### Algorithm

1. Load tx from file
2. For each cell_dep:
- Fetch cell
- If dep_type === 'dep_group':
- Decode cell.data as OutPointVec
- Fetch each referenced cell
- Add to mock_info.cell_deps
3. For each input:
- Fetch referenced cell
- Add to mock_info.inputs
4. Write JSON output
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@
"blessed": "0.1.81",
"chalk": "4.1.2",
"child_process": "^1.0.2",
"ckb-transaction-dumper": "^0.4.2",
"commander": "^12.0.0",
"http-proxy": "^1.18.1",
"https-proxy-agent": "^7.0.5",
Expand Down
17 changes: 8 additions & 9 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ program
const txHash = option.txHash;
if (option.singleScript) {
const { cellType, cellIndex, scriptType } = parseSingleScriptOption(option.singleScript);
return debugSingleScript(txHash, cellIndex, cellType, scriptType, option.network, option.bin);
return await debugSingleScript(txHash, cellIndex, cellType, scriptType, option.network, option.bin);
}
return debugTransaction(txHash, option.network);
return await debugTransaction(txHash, option.network);
});

program
Expand Down
12 changes: 6 additions & 6 deletions src/cmd/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import { Network } from '../type/base';
import { encodeBinPathForTerminal } from '../util/encoding';
import { logger } from '../util/logger';

export function debugTransaction(txHash: string, network: Network) {
const txFile = buildTxFileOptionBy(txHash, network);
export async function debugTransaction(txHash: string, network: Network) {
const txFile = await buildTxFileOptionBy(txHash, network);
const opts = buildTransactionDebugOptions(txHash, network);
for (const opt of opts) {
logger.section(opt.name, [], 'info');
Expand Down Expand Up @@ -48,15 +48,15 @@ export function buildTransactionDebugOptions(txHash: string, network: Network) {
return result;
}

export function debugSingleScript(
export async function debugSingleScript(
txHash: string,
cellIndex: number,
cellType: 'input' | 'output',
scriptType: 'type' | 'lock',
network: Network,
bin?: string,
) {
const txFile = buildTxFileOptionBy(txHash, network);
const txFile = await buildTxFileOptionBy(txHash, network);
let opt = `--cell-index ${cellIndex} --cell-type ${cellType} --script-group-type ${scriptType}`;
if (bin) {
opt = opt + ` --bin ${bin}`;
Expand All @@ -81,7 +81,7 @@ export function parseSingleScriptOption(value: string) {
};
}

export function buildTxFileOptionBy(txHash: string, network: Network) {
export async function buildTxFileOptionBy(txHash: string, network: Network) {
const settings = readSettings();
const outputFilePath = buildDebugFullTransactionFilePath(network, txHash);
if (!fs.existsSync(outputFilePath)) {
Expand All @@ -90,7 +90,7 @@ export function buildTxFileOptionBy(txHash: string, network: Network) {
if (!fs.existsSync(outputFilePath)) {
fs.mkdirSync(path.dirname(outputFilePath), { recursive: true });
}
dumpTransaction({ rpc, txJsonFilePath, outputFilePath });
await dumpTransaction({ rpc, txJsonFilePath, outputFilePath });
}
const opt = `--tx-file ${encodeBinPathForTerminal(outputFilePath)}`;
return opt;
Expand Down
Loading
Loading