Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get binding generation & publishing ready for 0.1 release #114

Merged
merged 11 commits into from
Jun 21, 2023
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,17 @@ jobs:
build:
strategy:
matrix:
toolchain: [ stable, beta ]
toolchain: [
stable,
beta,
1.60.0, # Our MSRV
]
include:
- toolchain: stable
check-fmt: true
build-uniffi: true
- toolchain: 1.60.0
msrv: true
runs-on: ubuntu-latest
steps:
- name: Checkout source code
Expand All @@ -20,17 +27,27 @@ jobs:
toolchain: ${{ matrix.toolchain }}
override: true
profile: minimal
- name: Pin packages to allow for MSRV
if: matrix.msrv
run: cargo update -p hashlink --precise "0.8.1" --verbose # hashlink 0.8.2 requires hashbrown 0.13, requiring 1.61.0
- name: Build on Rust ${{ matrix.toolchain }}
run: cargo build --verbose --color always
- name: Build with UniFFI support on Rust ${{ matrix.toolchain }}
if: matrix.build-uniffi
run: cargo build --features uniffi --verbose --color always
- name: Build documentation on Rust ${{ matrix.toolchain }}
run: |
cargo doc --release --verbose --color always
cargo doc --document-private-items --verbose --color always
- name: Check release build on Rust ${{ matrix.toolchain }}
run: cargo check --release --verbose --color always
- name: Check release build with UniFFI support on Rust ${{ matrix.toolchain }}
if: matrix.build-uniffi
run: cargo check --release --features uniffi --verbose --color always
- name: Test on Rust ${{ matrix.toolchain }}
run: cargo test
- name: Test with UniFFI support on Rust ${{ matrix.toolchain }}
if: matrix.build-uniffi
run: cargo test --features uniffi
- name: Check formatting on Rust ${{ matrix.toolchain }}
if: matrix.check-fmt
Expand Down
35 changes: 35 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// swift-tools-version:5.5
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let tag = "0.1-alpha.1"
tnull marked this conversation as resolved.
Show resolved Hide resolved
let checksum = "d91403566498f01cdaaafc07a9360ef661151e64075c6d83bbce4c9b5bfa7cee"
let url = "https://github.com/lightningdevkit/ldk-node/releases/download/\(tag)/LDKNodeFFI.xcframework.zip"

let package = Package(
name: "ldk-node",
platforms: [
.iOS(.v15),
.macOS(.v12),
],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "LDKNode",
targets: ["LDKNodeFFI", "LDKNode"]),
],
targets: [
.target(
name: "LDKNode",
dependencies: ["LDKNodeFFI"],
path: "./bindings/swift/Sources",
swiftSettings: [.unsafeFlags(["-suppress-warnings"])]
),
.binaryTarget(
name: "LDKNodeFFI",
url: url,
checksum: checksum
)
]
)
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ fn main() {

node.start().unwrap();

let funding_address = node.new_funding_address();
let funding_address = node.new_onchain_address();

// .. fund address ..

Expand Down Expand Up @@ -59,6 +59,9 @@ LDK Node currently comes with a decidedly opinionated set of design choices:
## Language Support
LDK Node itself is written in [Rust][rust] and may therefore be natively added as a library dependency to any `std` Rust program. However, beyond its Rust API it also offers language bindings for [Swift][swift], [Kotlin][kotlin], and [Python][python] based on the [UniFFI](https://github.com/mozilla/uniffi-rs/). Moreover, [Flutter bindings][flutter_bindings] are also available.

## MSRV
The Minimum Supported Rust Version (MSRV) is currently 1.60.0.

[api_docs]: https://docs.rs/ldk-node/*/ldk_node/
[api_docs_node]: https://docs.rs/ldk-node/*/ldk_node/struct.Node.html
[api_docs_builder]: https://docs.rs/ldk-node/*/ldk_node/struct.Builder.html
Expand Down
29 changes: 2 additions & 27 deletions bindings/kotlin/ldk-node-android/lib/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ afterEvaluate {
pom {
name.set("ldk-node-android")
description.set(
"LDK Node, a ready-to-go node implementation built using LDK."
"LDK Node, a ready-to-go Lightning node library built using LDK and BDK."
)
url.set("https://lightningdevkit.org")
licenses {
Expand All @@ -85,12 +85,7 @@ afterEvaluate {
developer {
id.set("tnull")
name.set("Elias Rohrer")
email.set("tnull@noreply.github.org")
}
developer {
id.set("jurvis")
name.set("Jurvis Tan")
email.set("jurvis@noreply.github.org")
email.set("dev@tnull.de")
}
}
scm {
Expand All @@ -111,23 +106,3 @@ signing {
useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword)
sign(publishing.publications)
}

//tasks.named<Test>("test") {
// // Use JUnit Platform for unit tests.
// useJUnitPlatform()
//
// testLogging {
// events(PASSED, SKIPPED, FAILED, STANDARD_OUT, STANDARD_ERROR)
// exceptionFormat = FULL
// showExceptions = true
// showCauses = true
// showStackTraces = true
// showStandardStreams = true
// }
//}

//// This task dependency ensures that we build the bindings
//// binaries before running the tests
//tasks.withType<KotlinCompile> {
// dependsOn("buildAndroidLib")
//}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
@RunWith(AndroidJUnit4::class)
class AndroidLibTest {
@Test fun node_start_stop() {
val network: Network = "regtest"
assertEquals(network, "regtest")
val network = Network.REGTEST

val tmpDir1 = createTempDirectory("ldk_node").toString()
println("Random dir 1: $tmpDir1")
Expand All @@ -27,8 +26,8 @@ class AndroidLibTest {
val listenAddress1 = "127.0.0.1:2323"
val listenAddress2 = "127.0.0.1:2324"

val config1 = Config(tmpDir1, "http://127.0.0.1:3002", network, listenAddress1, 2048u)
val config2 = Config(tmpDir2, "http://127.0.0.1:3002", network, listenAddress2, 2048u)
val config1 = Config(tmpDir1, network, listenAddress1, 2048u)
val config2 = Config(tmpDir2, network, listenAddress2, 2048u)

val builder1 = Builder.fromConfig(config1)
val builder2 = Builder.fromConfig(config2)
Expand All @@ -45,10 +44,10 @@ class AndroidLibTest {
val nodeId2 = node2.nodeId()
println("Node Id 2: $nodeId2")

val address1 = node1.newFundingAddress()
val address1 = node1.newOnchainAddress()
println("Funding address 1: $address1")

val address2 = node2.newFundingAddress()
val address2 = node2.newOnchainAddress()
println("Funding address 2: $address2")

node1.stop()
Expand Down
17 changes: 7 additions & 10 deletions bindings/kotlin/ldk-node-jvm/lib/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ afterEvaluate {
pom {
name.set("ldk-node-jvm")
description.set(
"LDK Node, a ready-to-go node implementation built using LDK."
"LDK Node, a ready-to-go Lightning node library built using LDK and BDK."
)
url.set("https://lightningdevkit.org")
licenses {
Expand All @@ -80,15 +80,12 @@ afterEvaluate {
}
}
developers {
developer {
id.set("tnull")
name.set("Elias Rohrer")
email.set("tnull@noreply.github.org")
}
developer {
id.set("jurvis")
name.set("Jurvis Tan")
email.set("jurvis@noreply.github.org")
developers {
developer {
id.set("tnull")
name.set("Elias Rohrer")
email.set("dev@tnull.de")
}
}
}
scm {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,19 @@ fun runCommandAndWait(cmd: String): String {
return stdout + stderr
}

fun mine(blocks: UInt) {
fun mine(blocks: UInt): String {
val address = runCommandAndWait("bitcoin-cli -regtest getnewaddress")
val output = runCommandAndWait("bitcoin-cli -regtest generatetoaddress $blocks $address")
println("Mining output: $output")
val re = Regex("\n.+\n\\]$")
val lastBlock = re.find(output)!!.value.replace("]","").replace("\"", "").replace("\n","").trim()
println("Last block: $lastBlock")
return lastBlock
}

fun mineAndWait(esploraEndpoint: String, blocks: UInt) {
val lastBlockHash = mine(blocks)
waitForBlock(esploraEndpoint, lastBlockHash)
}

fun sendToAddress(address: String, amountSats: UInt): String {
Expand All @@ -39,6 +48,7 @@ fun setup() {
runCommandAndWait("bitcoin-cli -regtest createwallet ldk_node_test")
runCommandAndWait("bitcoin-cli -regtest loadwallet ldk_node_test true")
mine(101u)
Thread.sleep(5_000)
}

fun waitForTx(esploraEndpoint: String, txid: String) {
Expand All @@ -53,16 +63,32 @@ fun waitForTx(esploraEndpoint: String, txid: String) {
val response = client.send(request, HttpResponse.BodyHandlers.ofString());

esploraPickedUpTx = re.containsMatchIn(response.body());
Thread.sleep(1_000)
Thread.sleep(500)
}
}

fun waitForBlock(esploraEndpoint: String, blockHash: String) {
var esploraPickedUpBlock = false
val re = Regex("\"in_best_chain\":true");
while (!esploraPickedUpBlock) {
val client = HttpClient.newBuilder().build()
val request = HttpRequest.newBuilder()
.uri(URI.create(esploraEndpoint + "/block/" + blockHash + "/status"))
.build();

val response = client.send(request, HttpResponse.BodyHandlers.ofString());
val body = response.body()

esploraPickedUpBlock = re.containsMatchIn(response.body());
Thread.sleep(500)
}
}

class LibraryTest {
@Test fun fullCycle() {
val esploraEndpoint = "http://127.0.0.1:3002"
setup()

val network = Network.REGTEST

val tmpDir1 = createTempDirectory("ldk_node").toString()
println("Random dir 1: $tmpDir1")
val tmpDir2 = createTempDirectory("ldk_node").toString()
Expand All @@ -71,13 +97,27 @@ class LibraryTest {
val listenAddress1 = "127.0.0.1:2323"
val listenAddress2 = "127.0.0.1:2324"

val esploraEndpoint = "http://127.0.0.1:3002"
val logLevel = LogLevel.TRACE;

val config1 = Config()
config1.storageDirPath = tmpDir1
config1.listeningAddress = listenAddress1
config1.network = Network.REGTEST
config1.logLevel = LogLevel.TRACE

val config1 = Config(tmpDir1, esploraEndpoint, network, listenAddress1, 2048u)
val config2 = Config(tmpDir2, esploraEndpoint, network, listenAddress2, 2048u)
println("Config 1: $config1")

val config2 = Config()
config2.storageDirPath = tmpDir2
config2.listeningAddress = listenAddress2
config2.network = Network.REGTEST
config2.logLevel = LogLevel.TRACE
println("Config 2: $config2")

val builder1 = Builder.fromConfig(config1)
builder1.setEsploraServer(esploraEndpoint)
val builder2 = Builder.fromConfig(config2)
builder2.setEsploraServer(esploraEndpoint)

val node1 = builder1.build()
val node2 = builder2.build()
Expand All @@ -91,15 +131,15 @@ class LibraryTest {
val nodeId2 = node2.nodeId()
println("Node Id 2: $nodeId2")

val address1 = node1.newFundingAddress()
val address1 = node1.newOnchainAddress()
println("Funding address 1: $address1")

val address2 = node2.newFundingAddress()
val address2 = node2.newOnchainAddress()
println("Funding address 2: $address2")

val txid1 = sendToAddress(address1, 100000u)
val txid2 = sendToAddress(address2, 100000u)
mine(6u)
mineAndWait(esploraEndpoint, 6u)

waitForTx(esploraEndpoint, txid1)
waitForTx(esploraEndpoint, txid2)
Expand Down Expand Up @@ -139,7 +179,7 @@ class LibraryTest {

waitForTx(esploraEndpoint, fundingTxid)

mine(6u)
mineAndWait(esploraEndpoint, 6u)

node1.syncWallets()
node2.syncWallets()
Expand Down Expand Up @@ -196,10 +236,7 @@ class LibraryTest {
assert(channelClosedEvent2 is Event.ChannelClosed)
node2.eventHandled()

mine(1u)

// Sleep a bit to allow for the block to propagate to esplora
Thread.sleep(5_000)
mineAndWait(esploraEndpoint, 1u)

node1.syncWallets()
node2.syncWallets()
Expand Down
2 changes: 1 addition & 1 deletion bindings/ldk_node.udl
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ interface LDKNode {
PublicKey node_id();
NetAddress? listening_address();
[Throws=NodeError]
Address new_funding_address();
Address new_onchain_address();
[Throws=NodeError]
Txid send_to_onchain_address([ByRef]Address address, u64 amount_msat);
[Throws=NodeError]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<key>LibraryIdentifier</key>
tnull marked this conversation as resolved.
Show resolved Hide resolved
<string>macos-arm64_x86_64</string>
<key>LibraryPath</key>
<string>ldk_nodeFFI.framework</string>
<string>LDKNodeFFI.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
Expand All @@ -21,7 +21,7 @@
<key>LibraryIdentifier</key>
<string>ios-arm64_x86_64-simulator</string>
<key>LibraryPath</key>
<string>ldk_nodeFFI.framework</string>
<string>LDKNodeFFI.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
Expand All @@ -36,7 +36,7 @@
<key>LibraryIdentifier</key>
<string>ios-arm64</string>
<key>LibraryPath</key>
<string>ldk_nodeFFI.framework</string>
<string>LDKNodeFFI.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// This is the "umbrella header" for our combined Rust code library.
// It needs to import all of the individual headers.

#import "ldk_nodeFFI.h"
#import "LDKNodeFFI.h"
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
framework module LDKNodeFFI {
umbrella header "LDKNodeFFI-umbrella.h"

export *
module * { export * }
}
Loading