bitcoin_test.js
Overview
`bitcoin_test.js` is a performance/load testing script designed to benchmark the Bitcoin blockchain API endpoints exposed by the ShapeShift Unchained platform. Utilizing the [k6](https://k6.io/) load testing tool, it simulates high-throughput traffic against two critical REST API endpoints:
Account endpoint: Retrieves Bitcoin account information based on extended public keys (xpubs).
UTXOs endpoint: Retrieves unspent transaction outputs (UTXOs) for Bitcoin accounts.
The script defines two concurrent test scenarios (`account` and `utxos`) that generate a constant arrival rate of HTTP GET requests for a duration of 5 minutes each. It uses a large predefined list of Bitcoin xpubs to cycle through requests, mimicking diverse user queries. Performance thresholds for request latency and failure rates are enforced to ensure API responsiveness and reliability under load.
This script is a vital part of the developer tooling and performance testing suite, enabling developers and QA teams to validate the scalability and robustness of the Bitcoin API layer before production deployment.
Detailed Components
Constants
xpubs
Type:
Array<string>Description: A hard-coded array containing a large set of Bitcoin extended public keys (xpubs). These xpubs serve as identifiers for Bitcoin accounts used during load testing.
Usage: Requests are made against API endpoints for each xpub in a round-robin fashion by indexing with modulo arithmetic on the current iteration number.
Exported Variables
options
Type:
ObjectPurpose: Configuration object for k6 scenarios and performance thresholds.
Structure:
export const options = {
scenarios: {
account: {
executor: 'constant-arrival-rate',
duration: "5m",
rate: 1000,
preAllocatedVUs: 1000,
maxVUs: 2500,
exec: 'account'
},
utxos: {
executor: 'constant-arrival-rate',
duration: "5m",
rate: 1000,
preAllocatedVUs: 1000,
maxVUs: 2500,
exec: 'utxos'
},
},
thresholds: {
'http_req_duration{scenario:account}': ['p(95) < 800'],
'http_req_duration{scenario:utxos}': ['p(95) < 800'],
'http_req_failed{scenario:account}': ['rate<0.01'],
'http_req_failed{scenario:utxos}': ['rate<0.01'],
'http_req_duration{status:200}': ['max>=0'],
'http_req_duration{status:429}': ['max>=0'],
},
summaryTrendStats: ['avg', 'min', 'med', 'max', 'p(90)', 'p(95)', 'p(99)', 'count'],
}
Scenarios:
account: Simulates 1000 requests per second for account info.utxos: Simulates 1000 requests per second for UTXO info.Both run for 5 minutes using a constant arrival rate executor.
Virtual Users (VUs) are pre-allocated and max VUs defined for concurrency control.
Thresholds:
95th percentile request duration per scenario must be under 800 milliseconds.
Failure rate (request errors) must remain below 1% (
rate<0.01).Tracks max durations for HTTP status codes 200 and 429 (rate limiting).
Summary stats: Specifies which statistical metrics k6 should report in the test summary.
Exported Functions
account()
Purpose: Executes one HTTP GET request to the Bitcoin account API endpoint for a specific xpub.
Parameters: None
Returns: None (performs HTTP GET via k6's
httpmodule)Implementation details:
Selects an xpub from the
xpubsarray by calculatingexec.scenario.iterationInTest % xpubs.lengthto evenly distribute requests.Constructs URL:
https://api.bitcoin.shapeshift.com/api/v1/account/{xpub}Calls
http.get()to issue the GET request.
Usage Example:
export function account() {
http.get(`https://api.bitcoin.shapeshift.com/api/v1/account/${xpubs[exec.scenario.iterationInTest % xpubs.length]}`)
}
Context: Used by the
accountscenario defined inoptions.
utxos()
Purpose: Executes one HTTP GET request to the Bitcoin UTXOs API endpoint for a specific xpub.
Parameters: None
Returns: None (performs HTTP GET via k6's
httpmodule)Implementation details:
Uses the same modulo logic as
account()to select an xpub.Constructs URL:
https://api.bitcoin.shapeshift.com/api/v1/account/{xpub}/utxosCalls
http.get()to issue the GET request.
Usage Example:
export function utxos() {
http.get(`https://api.bitcoin.shapeshift.com/api/v1/account/${xpubs[exec.scenario.iterationInTest % xpubs.length]}/utxos`)
}
Context: Used by the
utxosscenario defined inoptions.
handleSummary(data)
Purpose: Customizes the summary output after the test run completes.
Parameters:
data(Object): The full k6 test result data object.
Returns: An object mapping output file paths to their contents.
Implementation details:
Serializes the entire summary
dataobject to JSON.Writes it to
/out/bitcoin/results/result.json.Enables persistent storage of test results for post-test analysis or integration with CI/CD pipelines.
Usage Example:
export function handleSummary(data) {
return {
"/out/bitcoin/results/result.json": JSON.stringify(data),
}
}
Important Implementation Details
Load Distribution: The modulo operation on
exec.scenario.iterationInTestensures that requests cycle through the entirexpubslist evenly, simulating diversified user activity rather than hammering a single account repeatedly.Constant Arrival Rate Executor: Unlike ramping or fixed VUs, this executor guarantees a fixed number of iterations (requests) per second, regardless of how many VUs are active. This provides precise control over request rate, vital for consistent benchmarking.
Thresholds: The script enforces strict latency and error rate thresholds, helping detect performance regressions or instabilities during automated testing runs.
Large xpub Dataset: The extensive list of xpubs (~150+) helps mimic real-world load with many unique accounts, improving test realism.
Interaction with Other System Components
Target API: The script sends HTTP requests to the Bitcoin API hosted at
https://api.bitcoin.shapeshift.com/api/v1/account. This API is part of the ShapeShift Unchained platform's unified blockchain API layer.Docker Compose Environments: Typically, this script is run against services deployed locally or in staging via Docker Compose setups that instantiate the Bitcoin API server and its dependencies (blockchain node, indexer).
Performance Monitoring: The JSON summary output can feed into monitoring tools or dashboards, helping correlate load test results with system metrics.
Other k6 Scripts: This Bitcoin load test complements other blockchain-specific tests (e.g., Ethereum) in the
k6testing suite, enabling cross-coin performance benchmarking.
Visual Diagram: Flowchart of Load Test Execution
flowchart TD
Start[Test Start] --> Configure[Load options & scenarios]
Configure --> Init[Initialize VUs and iteration counter]
Init --> Loop{Iteration < Total Requests & Duration < 5m?}
Loop -->|Yes| SelectXpub[Select xpub via iterationInTest % length]
SelectXpub --> ChooseScenario{Which scenario?}
ChooseScenario -->|account| GETAccount[Send GET to /account/{xpub}]
ChooseScenario -->|utxos| GETUtxos[Send GET to /account/{xpub}/utxos]
GETAccount --> CollectMetrics[Collect response & metrics]
GETUtxos --> CollectMetrics
CollectMetrics --> Loop
Loop -->|No| Summarize[Generate summary statistics]
Summarize --> WriteOutput[Write JSON summary to file]
WriteOutput --> End[Test End]
Summary
`bitcoin_test.js` is a specialized k6 load test script that simulates sustained high-throughput HTTP GET traffic against Bitcoin account and UTXO API endpoints using a large dataset of xpubs. It employs constant arrival rate executors, enforces strict latency and failure thresholds, and outputs detailed JSON summaries for performance analysis. This script integrates tightly with local and staging environments orchestrated by Docker Compose and is part of the comprehensive developer tooling suite to ensure the ShapeShift Unchained Bitcoin API delivers reliable and scalable service under realistic loads.