-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
79 changed files
with
7,736 additions
and
399 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,36 @@ | ||
This is an experimental project to explore testing | ||
and deploying blockchain nodes at scale with an emphasis on local development and testing with batteries | ||
included for shipping to the cloud | ||
(or on-premise). | ||
> This is an **experimental** project to explore testing | ||
> and deploying blockchain nodes at scale with an emphasis on local development and testing with batteries | ||
> included for shipping to the cloud. | ||
Karfia is an open-source framework to define, test, deploy, | ||
and scale blockchain nodes on container-orchestration platforms. | ||
|
||
It packages complex blockchain nodes into a single definition that can be easily deployed | ||
and managed on Container-capable platforms such as Kubernetes, | ||
Docker Compose, and Testcontainers. | ||
|
||
## Motivation | ||
|
||
> Karfia (Καρφί, pronounced kar-fee) in Greek refers to a nail; | ||
Not so long ago, we had a single binary called Bitcoin Core that we could easily run with a single command. | ||
Having access to this single binary equated to having access to the node, wallet, and miner. | ||
It was simple and easy to use. | ||
If you had the binary and enough resources, you could run a full node that could do "everything". | ||
|
||
Then came the era of Bitcoin forks, new binaries, and new commands. | ||
Running a node is no longer as simple as typing `bitcoind` into the terminal. | ||
You need to know which binary to run, which command to use, and which flag to set. | ||
|
||
Soon enough, additional tools and capabilities were added to the mix. | ||
You need to run a separate binary for the wallet, another for the miner, another for the indexer, | ||
another for the consensus, another for the explorer, another for the API, and another for the RPC. | ||
|
||
As the complexity grew, it alienated the democratization of the blockchain. | ||
Running a node and participating in the network is no longer easy. | ||
Most developers today, even those familiar with the blockchain, | ||
rely on third-party providers to provide them with connectivity to the network. | ||
|
||
Karfia aims to solve this by restoring the simplicity of participating in the network, | ||
regardless of purpose, scale, complexity, and tenancy, | ||
to accelerate the adoption of blockchain technology. |
File renamed without changes.
83 changes: 83 additions & 0 deletions
83
definitions/bip122-000000000019d6689c085ae165831e93/bitcoind.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
{ | ||
"$schema": "./node_modules/karfia-definition/index.json", | ||
"id": "bip122:000000000019d6689c085ae165831e93/bitcoind:25.1", | ||
"caip2": "bip122:000000000019d6689c085ae165831e93", | ||
"name": "Bitcoin Mainnet", | ||
"environment": { | ||
"RPC_USER": { | ||
"type": "RandomBytes", | ||
"length": 16, | ||
"encoding": "hex" | ||
}, | ||
"RPC_PASSWORD": { | ||
"type": "RandomBytes", | ||
"length": 16, | ||
"encoding": "hex" | ||
} | ||
}, | ||
"containers": { | ||
"bitcoind": { | ||
"image": "docker.io/kylemanna/bitcoind@sha256:1492fa0306cb7eb5de8d50ba60367cff8d29b00b516e45e93e05f8b54fa2970e", | ||
"source": "https://github.com/kylemanna/docker-bitcoind", | ||
"endpoints": { | ||
"p2p": { | ||
"port": 8333 | ||
}, | ||
"rpc": { | ||
"port": 8332, | ||
"protocol": "HTTP JSON-RPC 2.0", | ||
"authorization": { | ||
"type": "HttpBasic", | ||
"username": { | ||
"key": "RPC_USER" | ||
}, | ||
"password": { | ||
"key": "RPC_PASSWORD" | ||
} | ||
}, | ||
"probes": { | ||
"readiness": { | ||
"method": "getblockchaininfo", | ||
"params": [], | ||
"match": { | ||
"result": { | ||
"type": "object", | ||
"properties": { | ||
"blocks": { | ||
"type": "number" | ||
} | ||
}, | ||
"required": ["blocks"] | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}, | ||
"resources": { | ||
"cpu": 1, | ||
"memory": 2048 | ||
}, | ||
"environment": { | ||
"DISABLE_WALLET": "1", | ||
"RPCUSER": { | ||
"key": "RPC_USER" | ||
}, | ||
"RPCPASSWORD": { | ||
"key": "RPC_PASSWORD" | ||
} | ||
}, | ||
"volumes": { | ||
"persistent": { | ||
"paths": ["/bitcoin/.bitcoin"], | ||
"size": { | ||
"initial": "600G", | ||
"from": "2024-01-01", | ||
"growth": "20G", | ||
"rate": "monthly" | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
200 changes: 200 additions & 0 deletions
200
definitions/bip122-000000000019d6689c085ae165831e93/bitcoind.unit.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,200 @@ | ||
import { afterAll, beforeAll, describe, expect, it } from '@jest/globals'; | ||
import { KarfiaAgentContainer, KarfiaTestContainer, KarfiaTestcontainers } from 'karfia-testcontainers'; | ||
import waitForExpect from 'wait-for-expect'; | ||
|
||
import definition from './bitcoind.json'; | ||
|
||
let testcontainers: KarfiaTestcontainers; | ||
|
||
beforeAll(async () => { | ||
testcontainers = await KarfiaTestcontainers.start(definition); | ||
}); | ||
|
||
afterAll(async () => { | ||
await testcontainers.stop(); | ||
}); | ||
|
||
describe('bitcoind', () => { | ||
let bitcoind: KarfiaTestContainer; | ||
|
||
beforeAll(() => { | ||
bitcoind = testcontainers.getContainer('bitcoind'); | ||
}); | ||
|
||
it('should get rpc port', async () => { | ||
const port = bitcoind.getHostPort('rpc'); | ||
expect(port).toStrictEqual(expect.any(Number)); | ||
}); | ||
|
||
it('should rpc getblockchaininfo', async () => { | ||
const response = await bitcoind.rpc({ | ||
method: 'getblockchaininfo', | ||
}); | ||
|
||
expect(response.status).toStrictEqual(200); | ||
|
||
expect(await response.json()).toMatchObject({ | ||
result: { | ||
bestblockhash: '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f', | ||
chain: 'main', | ||
}, | ||
}); | ||
}); | ||
|
||
it('should rpc getblockcount', async () => { | ||
const response = await bitcoind.rpc({ | ||
method: 'getblockcount', | ||
}); | ||
|
||
expect(response.status).toStrictEqual(200); | ||
|
||
expect(await response.json()).toMatchObject({ | ||
result: 0, | ||
}); | ||
}); | ||
|
||
it('should rpc getblock', async () => { | ||
const response = await bitcoind.rpc({ | ||
method: 'getblock', | ||
params: ['000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f', 2], | ||
}); | ||
|
||
expect(response.status).toStrictEqual(200); | ||
|
||
expect(await response.json()).toEqual({ | ||
error: null, | ||
id: expect.any(Number), | ||
result: { | ||
bits: '1d00ffff', | ||
chainwork: '0000000000000000000000000000000000000000000000000000000100010001', | ||
confirmations: 1, | ||
difficulty: 1, | ||
hash: '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f', | ||
height: 0, | ||
mediantime: 1231006505, | ||
merkleroot: '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b', | ||
nTx: 1, | ||
nonce: 2083236893, | ||
size: 285, | ||
strippedsize: 285, | ||
time: 1231006505, | ||
tx: [ | ||
{ | ||
hash: '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b', | ||
hex: '01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000', | ||
locktime: 0, | ||
size: 204, | ||
txid: '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b', | ||
version: 1, | ||
vin: [ | ||
{ | ||
coinbase: | ||
'04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73', | ||
sequence: 4294967295, | ||
}, | ||
], | ||
vout: [ | ||
{ | ||
n: 0, | ||
scriptPubKey: { | ||
asm: '04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f OP_CHECKSIG', | ||
desc: 'pk(04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f)#vlz6ztea', | ||
hex: '4104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac', | ||
type: 'pubkey', | ||
}, | ||
value: 50, | ||
}, | ||
], | ||
vsize: 204, | ||
weight: 816, | ||
}, | ||
], | ||
version: 1, | ||
versionHex: '00000001', | ||
weight: 1140, | ||
}, | ||
}); | ||
}); | ||
|
||
describe.skip('synchronization', () => { | ||
// Takes too long to run and is not deterministic | ||
beforeAll(async () => { | ||
await waitForExpect(async () => { | ||
const response = await bitcoind.rpc({ | ||
method: 'getblockcount', | ||
params: [], | ||
}); | ||
|
||
const result = ((await response.json()) as any).result; | ||
expect(result).toBeGreaterThan(1); | ||
}, 30000); | ||
}); | ||
|
||
it('should bitcoind.rpc getblock(1)', async () => { | ||
const response = await bitcoind.rpc({ | ||
method: 'getblock', | ||
params: ['00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048'], | ||
}); | ||
|
||
expect(response.status).toStrictEqual(200); | ||
expect(await response.json()).toEqual({}); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('karfia-agent', () => { | ||
let agent: KarfiaAgentContainer; | ||
|
||
beforeAll(() => { | ||
agent = testcontainers.getKarfiaAgent(); | ||
}); | ||
|
||
it('should get karfia-agent/deployment', async () => { | ||
const result = await agent.getDeployment(); | ||
expect(result).toMatchObject({ | ||
deploymentId: testcontainers.getDeploymentId(), | ||
definitionId: definition.id, | ||
caip2: definition.caip2, | ||
name: definition.name, | ||
}); | ||
}); | ||
|
||
it('should get karfia-agent/definition', async () => { | ||
const result = await agent.getDefinition(); | ||
const expected = { | ||
...definition, | ||
$schema: undefined, | ||
}; | ||
delete expected.$schema; | ||
expect(result).toMatchObject(expected); | ||
}); | ||
|
||
it('should get karfia-agent/probes/startup', async () => { | ||
const response = await agent.probe('startup'); | ||
expect(response.status).toStrictEqual(200); | ||
expect(await response.json()).toMatchObject({ | ||
ok: true, | ||
}); | ||
}); | ||
|
||
it('should get karfia-agent/probes/liveness', async () => { | ||
const response = await agent.probe('liveness'); | ||
expect(response.status).toStrictEqual(200); | ||
expect(await response.json()).toMatchObject({ | ||
ok: true, | ||
}); | ||
}); | ||
|
||
it('should get karfia-agent/probes/readiness', async () => { | ||
const response = await agent.probe('readiness'); | ||
expect(response.status).toStrictEqual(200); | ||
expect(await response.json()).toMatchObject({ | ||
containers: { | ||
bitcoind: { | ||
ok: true, | ||
}, | ||
}, | ||
ok: true, | ||
}); | ||
}); | ||
}); |
28 changes: 28 additions & 0 deletions
28
definitions/bip122-000000000019d6689c085ae165831e93/package.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{ | ||
"name": "@karfia/bip122-000000000019d6689c085ae165831e93", | ||
"version": "0.0.0", | ||
"private": false, | ||
"license": "MPL 2.0", | ||
"scripts": { | ||
"lint": "eslint .", | ||
"test": "jest" | ||
}, | ||
"lint-staged": { | ||
"*": [ | ||
"prettier --write --ignore-unknown" | ||
], | ||
"*.{ts,tsx}": [ | ||
"eslint --fix", | ||
"prettier --write" | ||
] | ||
}, | ||
"jest": { | ||
"preset": "@workspace/jest-preset" | ||
}, | ||
"devDependencies": { | ||
"@workspace/jest-preset": "workspace:*", | ||
"@workspace/tsconfig": "workspace:*", | ||
"karfia-definition": "workspace:*", | ||
"karfia-testcontainers": "workspace:*" | ||
} | ||
} |
File renamed without changes.
Oops, something went wrong.