PHP WebShell
Текущая директория: /opt/BitGoJS/modules/utxo-lib/test/integration_local_rpc/generate
Просмотр файла: main.ts
import * as assert from 'assert';
const utxolib = require('../../../src');
import { Network, getMainnet, getNetworkName, isTestnet } from '../../../src';
import { getRegtestNode, getRegtestNodeUrl, Node, getRegtestNodeHelp } from './regtestNode';
import {
createScriptPubKey,
createSpendTransaction,
createPsbtSpendTransaction,
isSupportedDepositType,
ScriptType,
scriptTypes,
getP2trMusig2Index,
} from './outputScripts.util';
import { RpcClient } from './RpcClient';
import {
fixtureKeys,
getProtocolVersions,
Protocol,
wipeFixtures,
writeTransactionFixtureWithInputs,
} from './fixtures';
import { isScriptType2Of3, isSupportedScriptType, ScriptType2Of3 } from '../../../src/bitgo/outputScripts';
import { sendFromFaucet, generateToFaucet } from './faucet';
import { getInternalChainCode, KeyName, RootWalletKeys, Tuple, ZcashTransaction } from '../../../src/bitgo';
function getScriptTypes() {
// FIXME(BG-66941): p2trMusig2 signing does not work in this test suite yet
// because the test suite is written with TransactionBuilder
return scriptTypes.filter((scriptType) => scriptType);
}
async function printRpcHelp(rpc: RpcClient, network: Network): Promise<void> {
console.log(await rpc.getHelp());
}
async function printNodeHelp(network: Network): Promise<void> {
const { stdout, stderr } = await getRegtestNodeHelp(network);
if (stderr) {
console.error(stderr);
throw new Error(`stderr`);
}
console.log(stdout);
}
async function initBlockchain(rpc: RpcClient, protocol: Protocol): Promise<void> {
let minBlocks = 300;
switch (protocol.network) {
case utxolib.networks.bitcoingoldTestnet:
// The actual BTC/BTG fork flag only gets activated at this height.
// On mainnet the height was at 491407 (Around 10/25/2017 12:00 UTC)
// Prior to that, signatures that use the BIP143 sighash flag are invalid.
// https://github.com/BTCGPU/BTCGPU/blob/71894be9/src/chainparams.cpp#L371
minBlocks = 2000;
break;
case utxolib.networks.dogecoinTest:
// Mine 1000 blocks to get at least 100 M doge to send
minBlocks = 1000;
break;
case utxolib.networks.zcashTest:
switch (protocol.version) {
case ZcashTransaction.VERSION4_BRANCH_CANOPY:
minBlocks = 400;
break;
case ZcashTransaction.VERSION4_BRANCH_NU5:
case ZcashTransaction.VERSION5_BRANCH_NU5:
minBlocks = 500;
break;
default:
throw new Error(`unexpected protocol version ${protocol.version}`);
}
break;
}
const diff = minBlocks - (await rpc.getBlockCount());
if (diff > 0) {
console.log(`mining ${diff} blocks to reach height ${minBlocks}`);
await generateToFaucet(rpc, diff);
}
}
function toRegtestAddress(network: { bech32?: string }, scriptType: ScriptType, script: Buffer): string {
if (scriptType === 'p2wsh' || scriptType === 'p2wkh' || scriptType === 'p2tr' || scriptType === 'p2trMusig2') {
switch (network) {
case utxolib.networks.testnet:
network = { bech32: 'bcrt' };
break;
case utxolib.networks.litecoinTest:
network = { bech32: 'rltc' };
break;
case utxolib.networks.bitcoingoldTestnet:
network = { bech32: 'btgrt' };
break;
}
}
return utxolib.address.fromOutputScript(script, network);
}
function getSpendTx(
scriptType: ScriptType2Of3,
inputTxs: Buffer[],
script,
protocol: Protocol,
amountType: 'number' | 'bigint',
p2trMusig2SpendType?: 'keyPath' | 'scriptPath'
) {
if (scriptType === 'p2trMusig2') {
if (!p2trMusig2SpendType) {
throw new Error('Invalid p2tr spend type');
}
const index = getP2trMusig2Index(p2trMusig2SpendType);
const signers: Tuple<KeyName> = p2trMusig2SpendType === 'keyPath' ? ['user', 'bitgo'] : ['user', 'backup'];
const rootWalletKeys = new RootWalletKeys(fixtureKeys);
return createPsbtSpendTransaction({
rootWalletKeys,
chain: getInternalChainCode(scriptType),
index,
signers,
inputTxs,
network: protocol.network,
version: protocol.version,
amountType,
});
} else {
return createSpendTransaction(
fixtureKeys,
scriptType,
inputTxs,
script,
protocol.network,
protocol.version,
amountType
);
}
}
async function createTransactionsForScriptType(
rpc: RpcClient,
scriptType: ScriptType,
protocol: Protocol,
p2trMusig2SpendType?: 'keyPath' | 'scriptPath'
): Promise<void> {
const fullScriptType = `${scriptType}${p2trMusig2SpendType ? p2trMusig2SpendType : ''}`;
const logTag = `createTransaction ${fullScriptType} ${getNetworkName(protocol.network)} v=${protocol.version}`;
if (!isSupportedDepositType(protocol.network, scriptType)) {
console.log(logTag + ': not supported, skipping');
return;
}
console.log(logTag);
let keys = fixtureKeys;
if (scriptType === 'p2trMusig2') {
if (!p2trMusig2SpendType) {
throw new Error('Invalid p2tr spend type');
}
const index = getP2trMusig2Index(p2trMusig2SpendType);
const rootWalletKeys = new RootWalletKeys(fixtureKeys);
keys = rootWalletKeys.deriveForChainAndIndex(getInternalChainCode(scriptType), index).triple;
}
const script = createScriptPubKey(keys, scriptType, protocol.network);
const address = toRegtestAddress(protocol.network as { bech32: string }, scriptType, script);
const deposit1Txid = await sendFromFaucet(rpc, address, 1);
const deposit1Tx = await rpc.getRawTransaction(deposit1Txid);
await writeTransactionFixtureWithInputs(rpc, protocol, `deposit_${fullScriptType}.json`, deposit1Txid);
if (!isScriptType2Of3(scriptType) || !isSupportedScriptType(protocol.network, scriptType)) {
console.log(logTag + ': spend not supported, skipping spend');
return;
}
let amount: number | string = 1;
switch (protocol.network) {
case utxolib.networks.dogecoinTest:
// Exercise bigint precision with an amount > 100M and also where number would lose precision
amount = 109999998.00000001;
break;
}
const deposit2Txid = await sendFromFaucet(rpc, address, amount);
const deposit2Tx = await rpc.getRawTransaction(deposit2Txid);
let spendTx;
switch (protocol.network) {
case utxolib.networks.dogecoinTest:
spendTx = getSpendTx(scriptType, [deposit1Tx, deposit2Tx], script, protocol, 'bigint');
break;
default:
spendTx = getSpendTx(scriptType, [deposit1Tx, deposit2Tx], script, protocol, 'number', p2trMusig2SpendType);
break;
}
const spendTxid = await rpc.sendRawTransaction(spendTx.toBuffer());
assert.strictEqual(spendTxid, spendTx.getId());
await writeTransactionFixtureWithInputs(rpc, protocol, `spend_${fullScriptType}.json`, spendTxid);
}
async function createTransactions(rpc: RpcClient, protocol: Protocol) {
for (const scriptType of getScriptTypes()) {
if (scriptType === 'p2trMusig2') {
await createTransactionsForScriptType(rpc, scriptType, protocol, 'keyPath');
await createTransactionsForScriptType(rpc, scriptType, protocol, 'scriptPath');
} else {
await createTransactionsForScriptType(rpc, scriptType, protocol);
}
}
}
async function withRpcClient(protocol: Protocol, f: (c: RpcClient) => Promise<void>): Promise<void> {
await wipeFixtures(protocol);
let rpc;
let node: Node | undefined;
if (process.env.UTXOLIB_TESTS_USE_DOCKER === '1') {
node = await getRegtestNode(protocol.network);
rpc = await RpcClient.forUrlWait(protocol.network, getRegtestNodeUrl(protocol.network));
} else {
rpc = await RpcClient.fromEnvvar(protocol.network);
}
try {
await f(rpc);
} catch (e) {
console.error(`error for network ${getNetworkName(protocol.network)}`);
throw e;
} finally {
if (node) {
await node.stop();
}
}
}
async function run(protocol: Protocol) {
await withRpcClient(protocol, async (rpc) => {
if (process.env.UTXOLIB_TESTS_PRINT_RPC_HELP === '1') {
await printRpcHelp(rpc, protocol.network);
} else {
await initBlockchain(rpc, protocol);
await createTransactions(rpc, protocol);
}
});
}
async function main(args: string[]) {
const allowedNetworks = args.map((name) => {
const network = utxolib.networks[name];
if (!network) {
throw new Error(`invalid network ${name}`);
}
return getMainnet(network);
});
for (const networkName of Object.keys(utxolib.networks)) {
const network: Network = utxolib.networks[networkName];
if (!isTestnet(network)) {
continue;
}
if (allowedNetworks.length && !allowedNetworks.some((n) => n === getMainnet(network))) {
console.log(`skipping ${networkName}`);
continue;
}
if (process.env.UTXOLIB_TESTS_PRINT_NODE_HELP === '1') {
await printNodeHelp(network);
continue;
}
for (const version of getProtocolVersions(network)) {
await run({ network, version });
}
}
}
if (require.main === module) {
main(process.argv.slice(2)).catch((e) => {
console.error(e);
process.exit(1);
});
}
Выполнить команду
Для локальной разработки. Не используйте в интернете!