From aa843da4ac4c538073c0244334500511998c0423 Mon Sep 17 00:00:00 2001 From: Otto Allmendinger Date: Tue, 13 Jun 2023 11:43:58 +0200 Subject: [PATCH] feat(unspents): add docs/input-costs.md, generation tool Issue: BTC-0 --- modules/unspents/bin/generate_tables.ts | 94 +++++++++++++++++++++++++ modules/unspents/docs/input-costs.md | 13 ++++ modules/unspents/tsconfig.json | 2 +- 3 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 modules/unspents/bin/generate_tables.ts create mode 100644 modules/unspents/docs/input-costs.md diff --git a/modules/unspents/bin/generate_tables.ts b/modules/unspents/bin/generate_tables.ts new file mode 100644 index 0000000000..e9b22694e1 --- /dev/null +++ b/modules/unspents/bin/generate_tables.ts @@ -0,0 +1,94 @@ +import * as fs from 'fs/promises'; +import * as utxolib from '@bitgo/utxo-lib'; + +import { Dimensions } from '../src'; + +const headers = [ + 'Script Type', + 'Chain Codes', + 'Spend Type', + 'Input Size (Virtual Bytes)', + 'Relative Size (p2trMusig2 = 1.00)', +]; + +const relativeCostRef = Dimensions.fromScriptType('taprootKeyPathSpend').getInputsVSize(); + +type Row = [string, string, string, string, string]; + +function formatMarkdownTable(headers: string[], rows: string[][]): string { + return [headers, headers.map(() => '---'), ...rows].map((row) => `| ${row.join(' | ')} |`).join('\n'); +} + +function generateRowsForScriptType( + headers: string[], + t: utxolib.bitgo.outputScripts.ScriptType2Of3, + params?: { + spendTypeName: string; + scriptTypeParams: { scriptPathLevel?: number }; + } +): Row[] { + const chainCode = utxolib.bitgo.toChainPair(t); + + if (!params) { + if (t === 'p2tr') { + return [ + ...generateRowsForScriptType(headers, t, { + spendTypeName: 'Script Path, Level 2 (Backup/User, Backup/BitGo)', + scriptTypeParams: { scriptPathLevel: 2 }, + }), + ...generateRowsForScriptType(headers, t, { + spendTypeName: 'Script Path, Level 1 (User/BitGo)', + scriptTypeParams: { scriptPathLevel: 1 }, + }), + ]; + } + + if (t === 'p2trMusig2') { + return [ + ...generateRowsForScriptType(headers, t, { + spendTypeName: 'Script Path (Backup/User, Backup/BitGo)', + scriptTypeParams: { scriptPathLevel: 1 }, + }), + ...generateRowsForScriptType(headers, t, { + spendTypeName: 'Key Path (User/BitGo)', + scriptTypeParams: { scriptPathLevel: undefined }, + }), + ]; + } + } + + const inputVSize = Dimensions.fromScriptType(t, params?.scriptTypeParams).getInputsVSize(); + const row: Row = [ + t, + chainCode.join(`/`), + params?.spendTypeName ?? 'all', + inputVSize.toString(), + (inputVSize / relativeCostRef).toFixed(2), + ]; + return [row]; +} + +function generateTables() { + const scriptTypes = [...utxolib.bitgo.outputScripts.scriptTypes2Of3]; + return formatMarkdownTable( + headers, + scriptTypes.flatMap((s) => generateRowsForScriptType(headers, s)) + ); +} + +function generateDocument() { + return [ + '# Input Costs', + 'This document contains the worst-case input costs for various script types and spend types.', + 'The input costs are calculated using the `Dimensions` class from `@bitgo/unspents`.', + '', + generateTables(), + ].join('\n'); +} + +if (require.main === module) { + const outfile = 'docs/input-costs.md'; + fs.writeFile(outfile, generateDocument()) + .then(() => console.log('wrote to', outfile)) + .catch((e) => console.error(e)); +} diff --git a/modules/unspents/docs/input-costs.md b/modules/unspents/docs/input-costs.md new file mode 100644 index 0000000000..2dfb6af9f8 --- /dev/null +++ b/modules/unspents/docs/input-costs.md @@ -0,0 +1,13 @@ +# Input Costs +This document contains the worst-case input costs for various script types and spend types. +The input costs are calculated using the `Dimensions` class from `@bitgo/unspents`. + +| Script Type | Chain Codes | Spend Type | Input Size (Virtual Bytes) | Relative Size (p2trMusig2 = 1.00) | +| --- | --- | --- | --- | --- | +| p2sh | 0/1 | all | 298 | 5.14 | +| p2shP2wsh | 10/11 | all | 140 | 2.41 | +| p2wsh | 20/21 | all | 105 | 1.81 | +| p2tr | 30/31 | Script Path, Level 2 (Backup/User, Backup/BitGo) | 116 | 2.00 | +| p2tr | 30/31 | Script Path, Level 1 (User/BitGo) | 108 | 1.86 | +| p2trMusig2 | 40/41 | Script Path (Backup/User, Backup/BitGo) | 108 | 1.86 | +| p2trMusig2 | 40/41 | Key Path (User/BitGo) | 58 | 1.00 | \ No newline at end of file diff --git a/modules/unspents/tsconfig.json b/modules/unspents/tsconfig.json index faa90dc4a6..96b5d903db 100644 --- a/modules/unspents/tsconfig.json +++ b/modules/unspents/tsconfig.json @@ -11,5 +11,5 @@ "allowJs": false, "strict": true }, - "include": ["src/**/*", "test/**/*"] + "include": ["src/**/*", "test/**/*", "bin/**/*"] }