Skip to content

Commit 89d08f5

Browse files
committed
Remove the need for bitcoin full node
This commit adds middleware that uses GWallet's existing electrum client to help RGS verify utxos while removing the need for bitcoin full node.
1 parent 32ac36a commit 89d08f5

File tree

10 files changed

+161
-33
lines changed

10 files changed

+161
-33
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "geewallet"]
2+
path = geewallet
3+
url = https://github.com/aarani/geewallet.git

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ lightning-net-tokio = { version = "0.0.112" }
1111
tokio = { version = "1.14.1", features = ["full"] }
1212
tokio-postgres = { version="0.7.5" }
1313
futures = "0.3"
14+
hex = "0.4.3"
1415

1516
[profile.release]
1617
opt-level = 3
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
*.swp
2+
*.*~
3+
project.lock.json
4+
.DS_Store
5+
*.pyc
6+
nupkg/
7+
8+
# Visual Studio Code
9+
.vscode
10+
11+
# Rider
12+
.idea
13+
14+
# User-specific files
15+
*.suo
16+
*.user
17+
*.userosscache
18+
*.sln.docstates
19+
20+
# Build results
21+
[Dd]ebug/
22+
[Dd]ebugPublic/
23+
[Rr]elease/
24+
[Rr]eleases/
25+
x64/
26+
x86/
27+
build/
28+
bld/
29+
[Bb]in/
30+
[Oo]bj/
31+
[Oo]ut/
32+
msbuild.log
33+
msbuild.err
34+
msbuild.wrn
35+
36+
# Visual Studio 2015
37+
.vs/
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
open System
2+
open System.Threading.Tasks
3+
open Microsoft.AspNetCore.Builder
4+
open Microsoft.Extensions.Hosting
5+
6+
open GWallet.Backend
7+
open GWallet.Backend.UtxoCoin
8+
9+
[<EntryPoint>]
10+
let main args =
11+
let builder = WebApplication.CreateBuilder args
12+
let app = builder.Build()
13+
14+
app.Urls.Add "http://0.0.0.0:5108"
15+
16+
app.MapGet("/getTransaction/{height}/{txPos}",
17+
Func<string, string, Task<string>>(
18+
fun height txPos ->
19+
task {
20+
Console.WriteLine(sprintf "Request: looking for transaction #%s at block height #%s" txPos height)
21+
22+
let height = Convert.ToUInt32 height
23+
let txPos = Convert.ToUInt32 txPos
24+
25+
let querySettings =
26+
QuerySettings.Default ServerSelectionMode.Fast
27+
28+
let getTransactionFromPosIdJob = ElectrumClient.GetBlockchainTransactionIdFromPos height txPos
29+
let! txId =
30+
Server.Query Currency.BTC querySettings getTransactionFromPosIdJob None
31+
32+
let getTransactionJob = ElectrumClient.GetBlockchainTransaction txId
33+
let! tx =
34+
Server.Query Currency.BTC querySettings getTransactionJob None
35+
36+
return tx
37+
}
38+
)
39+
) |> ignore
40+
41+
app.Run()
42+
43+
0 // Exit code
44+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net6.0</TargetFramework>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<Compile Include="Program.fs" />
9+
</ItemGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="NBitcoin" Version="6.0.17" />
13+
</ItemGroup>
14+
15+
<ItemGroup>
16+
<ProjectReference Include="..\geewallet\src\GWallet.Backend\GWallet.Backend.fsproj" />
17+
</ItemGroup>
18+
19+
</Project>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft.AspNetCore": "Warning"
6+
}
7+
}
8+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"Logging": {
3+
"LogLevel": {
4+
"Default": "Information",
5+
"Microsoft.AspNetCore": "Warning"
6+
}
7+
},
8+
"AllowedHosts": "*"
9+
}

geewallet

Submodule geewallet added at 7626a16

src/config.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@ pub(crate) fn db_connection_config() -> Config {
3535
config
3636
}
3737

38-
pub(crate) fn bitcoin_rest_endpoint() -> HttpEndpoint {
39-
let host = env::var("BITCOIN_REST_DOMAIN").unwrap_or("127.0.0.1".to_string());
40-
let port = env::var("BITCOIN_REST_PORT")
41-
.unwrap_or("8332".to_string())
38+
pub(crate) fn middleware_rest_endpoint() -> HttpEndpoint {
39+
let host = env::var("MIDDLEWARE_REST_DOMAIN").unwrap_or("127.0.0.1".to_string());
40+
let port = env::var("MIDDLEWARE_REST_PORT")
41+
.unwrap_or("5108".to_string())
4242
.parse::<u16>()
43-
.expect("BITCOIN_REST_PORT env variable must be a u16.");
44-
let path = env::var("BITCOIN_REST_PATH").unwrap_or("/rest/".to_string());
43+
.expect("MIDDLEWARE_REST_PORT env variable must be a u16.");
44+
let path = env::var("MIDDLEWARE_REST_PATH").unwrap_or("/".to_string());
4545
HttpEndpoint::for_host(host).with_port(port).with_path(path)
4646
}
4747

src/verifier.rs

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1+
use hex;
12
use std::convert::TryInto;
23

3-
use bitcoin::{BlockHash, TxOut};
4-
use bitcoin::blockdata::block::Block;
5-
use bitcoin::hashes::Hash;
4+
use bitcoin::{BlockHash, TxOut, Transaction};
5+
use bitcoin::consensus::deserialize;
66
use lightning::chain;
77
use lightning::chain::AccessError;
8-
use lightning_block_sync::{BlockData, BlockSource};
98
use lightning_block_sync::http::BinaryResponse;
109
use lightning_block_sync::rest::RestClient;
1110

@@ -20,32 +19,42 @@ struct RestBinaryResponse(Vec<u8>);
2019
impl ChainVerifier {
2120
pub(crate) fn new() -> Self {
2221
ChainVerifier {
23-
rest_client: RestClient::new(config::bitcoin_rest_endpoint()).unwrap(),
22+
rest_client: RestClient::new(config::middleware_rest_endpoint()).unwrap(),
2423
}
2524
}
2625

27-
fn retrieve_block(&self, block_height: u32) -> Result<Block, AccessError> {
26+
fn retrieve_tx(&self, block_height: u32, transaction_index: u32) -> Result<Transaction, AccessError> {
2827
tokio::task::block_in_place(move || { tokio::runtime::Handle::current().block_on(async move {
29-
let uri = format!("blockhashbyheight/{}.bin", block_height);
30-
let block_hash_result =
28+
let uri = format!("getTransaction/{}/{}", block_height, transaction_index);
29+
let tx_result =
3130
self.rest_client.request_resource::<BinaryResponse, RestBinaryResponse>(&uri).await;
32-
let block_hash: Vec<u8> = block_hash_result.map_err(|error| {
33-
eprintln!("Could't find block hash at height {}: {}", block_height, error.to_string());
31+
let tx_hex_in_bytes: Vec<u8> = tx_result.map_err(|error| {
32+
eprintln!("Could't find transaction at height {} and pos {}: {}", block_height, transaction_index, error.to_string());
3433
AccessError::UnknownChain
3534
})?.0;
36-
let block_hash = BlockHash::from_slice(&block_hash).unwrap();
3735

38-
let block_result = self.rest_client.get_block(&block_hash).await;
39-
match block_result {
40-
Ok(BlockData::FullBlock(block)) => {
41-
Ok(block)
42-
},
43-
Ok(_) => unreachable!(),
44-
Err(error) => {
45-
eprintln!("Couldn't retrieve block {}: {:?} ({})", block_height, error, block_hash);
46-
Err(AccessError::UnknownChain)
47-
}
48-
}
36+
let tx_hex_in_string =
37+
String::from_utf8(tx_hex_in_bytes)
38+
.map_err(|non_utf8| String::from_utf8_lossy(non_utf8.as_bytes()).into_owned())
39+
.unwrap();
40+
41+
let tx_bytes =
42+
hex::decode(tx_hex_in_string)
43+
.map_err(|error| {
44+
eprintln!("Could't find transaction at height {} and pos {}: {}", block_height, transaction_index, error.to_string());
45+
AccessError::UnknownChain
46+
})
47+
.unwrap();
48+
49+
let transaction =
50+
deserialize::<Transaction>(tx_bytes.as_slice())
51+
.map_err(|error| {
52+
eprintln!("Could't find transaction at height {} and pos {}: {}", block_height, transaction_index, error.to_string());
53+
AccessError::UnknownChain
54+
})
55+
.unwrap();
56+
57+
Ok(transaction)
4958
}) })
5059
}
5160
}
@@ -56,11 +65,8 @@ impl chain::Access for ChainVerifier {
5665
let transaction_index = ((short_channel_id >> 2 * 8) & 0xffffff) as u32;
5766
let output_index = (short_channel_id & 0xffff) as u16;
5867

59-
let block = self.retrieve_block(block_height)?;
60-
let transaction = block.txdata.get(transaction_index as usize).ok_or_else(|| {
61-
eprintln!("Transaction index {} out of bounds in block {} ({})", transaction_index, block_height, block.block_hash().to_string());
62-
AccessError::UnknownTx
63-
})?;
68+
let transaction = self.retrieve_tx(block_height, transaction_index)?;
69+
6470
let output = transaction.output.get(output_index as usize).ok_or_else(|| {
6571
eprintln!("Output index {} out of bounds in transaction {}", output_index, transaction.txid().to_string());
6672
AccessError::UnknownTx

0 commit comments

Comments
 (0)