I’m increasingly worried about censorship and other attacks in the P2P network (see, eg, https://twitter.com/TheBlueMatt/status/1160620919775211520). While obviously making the net_processing p2p implementation more robust should be the focus (eg #15759), adding more redundancy in every way is also key. To avoid needless review burden on such systems, I think rust is an ideal candidate: it is wholly optional so we don’t just right to requiring Rust for Bitcoin Core, but building with it still provides real benefit, plus we can use compile-time checks to catch any overflows and memory corruption bugs to reduce review burden.
This PR implements a simple API for Rust code to fetch headers and blocks and then implements a sample client that can sync the chain using a REST endpoint. As a demo, I provide a rest endpoint over cloudflare at http://cloudflare.deanonymizingseed.com/rest/ so you should be able to fully sync the chain (albeit very slowly) with bitcoind -blockfetchrest=http://cloudflare.deanonymizingseed.com/rest/ -connect=0
There’s a few things to do before this is mergable, but I’d like feedback on the idea, and would like to also have a fully parallel, in rust, P2P net layer that is similarly simple and provides a nice redundant implementation in the future.
fanquake added the label
Brainstorming
on Aug 29, 2019
fanquake added the label
Needs Conceptual Review
on Aug 29, 2019
fanquake added the label
P2P
on Aug 29, 2019
TheBlueMatt force-pushed
on Aug 29, 2019
TheBlueMatt force-pushed
on Aug 29, 2019
TheBlueMatt force-pushed
on Aug 29, 2019
DrahtBot
commented at 11:53 pm on August 29, 2019:
member
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
Conflicts
Reviewers, this pull request conflicts with the following ones:
#17783 (util: Fix -norpcwhitelist, -norpcallowip, and similar corner case behavior by ryanofsky)
#17581 (refactor: Remove settings merge reverse precedence code by ryanofsky)
#17580 (refactor: Add ALLOW_LIST flags and enforce usage in CheckArgFlags by ryanofsky)
#17493 (util: Forbid ambiguous multiple assignments in config file by ryanofsky)
#17452 (test: update fuzz directory in .gitignore by jonatack)
#15367 (feature: Added ability for users to add a startup command by benthecarman)
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.
@jonasschnelli Yes ld on macOS doesn’t support --start-group or --end-group. This was a bit of a hack to fix a circular dependency issue Matt was seeing on his Debian machine. If you want to compile on macOS you should just be able to drop the -Wl,--start-group additions, as that has been working for me. We’ll need to fix this properly soon.
practicalswift
commented at 12:46 pm on August 30, 2019:
contributor
Interesting idea: cautious concept ACK – more redundancy is good and it is hard to see how this would make us worse off in any way as long as the existing P2P logic is kept unchanged. (Intentionally not commenting on the implementation and more specifically the pros and cons of pulling in Rust code: that is an implementation detail that I’m sure will be discussed separately post concept ACK/NACK.)
Censorship scenarios worth thinking about:
Even if we do the over-REST block downloads over HTTPS it should be noted that the TLS handshake leaks the hostname of the connected to service to passive eavesdroppers. (Unless TLS 1.3 + Encrypted SNI is used: super rare in practice though.)
The hostname is obviously also leaked when doing the DNS lookup. (Unless DoH (DNS over HTTPS) or DoT (DNS over TLS) is used: quite rare in practice.)
This allows for active censorship attacks if the hostnames used are only used for Bitcoin purposes (such as in the cloudflare.deanonymizingseed.com example – I understand it is just used here as an example).
(The same obviously goes for the IP-address used: if the IP-address connected to is only used for Bitcoin purposes then access to that IP-address could trivially be null routed without any non-Bitcoin users noticing.)
I guess one way to achieve (partial) censorship resistance is to download over HTTPS URLs where the hostnames used are mostly used for non-Bitcoin purposes (such as github.com – just used here as an example: I’m sure we can come up with other examples). That would leak the hostname but since the hostname and the IP address is used for other purposes it would still be hard for an attacker to block it without having non-Bitcoin users complain.
Another route would be to use TLS 1.3 + Encrypted SNI + DoH/DoT to connect to a service whose IP-address(es) are used mostly for non-Bitcoin purposes (such as CloudFlare which luckily supports both TLS 1.3 and Encrypted SNI). That wouldn’t leak the hostname and the IP-address would be hard to null route for an attacker without having non-Bitcoin users complain.
TheBlueMatt
commented at 6:33 pm on August 30, 2019:
member
Intentionally not commenting on the implementation and more specifically the pros and cons of pulling in Rust code: that is an implementation detail that I’m sure will be discussed separately post concept ACK/NACK
Right, there’s a few things that would need to happen to get this in mergeable state (notably buildsystem things), so no need for that just yet.
Censorship scenarios worth thinking about:
Right, two things I’d like to support in the blocks-over-REST module: domain fronting avoids most of the gnarly issues with SNI/DNS lookups breaking your privacy, though sadly many providers don’t like it anymore, and Tor support, possibly even with some default onion service recommended as a backup cause privacy is less of a concern there.
I’d also like to build a whole second P2P implementation (though with an explicit goal of being inefficient and simple, with the same trick as here where you wait 30 seconds before deciding to download anything to avoid wasting bandwidth), but first need to land some bit of rust downloading, and this seemed like an easier target.
TheBlueMatt force-pushed
on Aug 30, 2019
kristapsk
commented at 7:46 pm on August 30, 2019:
contributor
But why Rust not C++?
TheBlueMatt
commented at 5:59 am on August 31, 2019:
member
But why Rust not C++?
Because we can trivially turn on compile-time checking preventing a ton of classes of vulnerabilities (especially for network-facing code), and runtime checking for many other classes (like buffer overflows, at least those the compiler can’t prove aren’t possible).
fanquake
commented at 6:01 am on August 31, 2019:
member
I’m fairly Concept ACK on this. It’s been in discussion for a little while, and I’m pretty sure it came up at the last Core dev meetup as well?
But why Rust not C++?
@kristapsk This PR isn’t really the place to have that discussion and is only going to distract from what’s actually trying to be achieved. Although Matt points out one big advantage:
plus we can use compile-time checks to catch any overflows and memory corruption bugs to reduce review burden.
If you’d like to discuss Rust inside Bitcoin Core further, I’d suggest taking a look at #15798. Here are Cory’s thoughts on Rust from that thread:
Why rust? I don’t know. Maybe not. But I think it’s a fair assumption to say that Rust code will eventually end up in Bitcoin Core as the result of adding a new dependency. Adoption is happing quickly. So, I think it prudent to look ahead and not only be prepared, but actively help usher it in. Already I have a few things that I would like to work on and upstream to rust-lang to make our integration nicer, and I assume that more will be uncovered as it actually gets used.
I built and tested that this functions using the instructions above. The backup downloader kicked off after a 10 minute wait
0src/bitcoind -blockfetchrest=http://cloudflare.deanonymizingseed.com/rest/ -connect=0 1 22019-08-31T05:37:06Z nBestHeight=311015 32019-08-31T05:37:06Z init message: Loading P2P addresses...
42019-08-31T05:37:06Z Imported mempool transactions from disk: 0 succeeded, 0 failed, 0 expired, 0 already there
52019-08-31T05:37:06Z Loaded 63409 addresses from peers.dat 159ms
62019-08-31T05:37:06Z init message: Starting network threads...
72019-08-31T05:37:06Z DNS seeding disabled
82019-08-31T05:37:06Z net thread start
92019-08-31T05:37:06Z msghand thread start
102019-08-31T05:37:06Z addcon thread start
112019-08-31T05:37:06Z init message: Done loading
122019-08-31T05:47:10Z Synchronizing blockheaders, height: 313014(~53.91%)132019-08-31T05:47:13Z Synchronizing blockheaders, height: 315013(~54.23%)142019-08-31T05:47:15Z Synchronizing blockheaders, height: 317012(~54.55%)152019-08-31T05:47:17Z Synchronizing blockheaders, height: 319011(~54.87%)16< snip >
172019-08-31T05:52:27Z Synchronizing blockheaders, height: 574883(~97.17%)182019-08-31T05:52:34Z Synchronizing blockheaders, height: 576882(~97.49%)192019-08-31T05:52:36Z Synchronizing blockheaders, height: 578881(~97.81%)202019-08-31T05:52:39Z Synchronizing blockheaders, height: 580880(~98.14%)212019-08-31T05:52:41Z Synchronizing blockheaders, height: 582879(~98.46%)222019-08-31T05:52:44Z Synchronizing blockheaders, height: 584878(~98.76%)232019-08-31T05:52:47Z Synchronizing blockheaders, height: 586877(~99.09%)242019-08-31T05:52:49Z Synchronizing blockheaders, height: 588876(~99.40%)252019-08-31T05:52:56Z Synchronizing blockheaders, height: 590875(~99.73%)262019-08-31T05:52:59Z Synchronizing blockheaders, height: 592551(~100.00%)272019-08-31T05:53:35Z Pre-allocating up to position 0x3000000 in blk00158.dat
282019-08-31T05:53:35Z Pre-allocating up to position 0x100000 in rev00158.dat
292019-08-31T05:53:35Z UpdateTip: new best=0000000000000000246039d52e90fb6b7cd442dda19861fb948c28e3a44f7a4e height=311016version=0x00000002 log2_work=79.744641 tx=42644694date='2014-07-16T13:51:22Z'progress=0.095646 cache=0.5MiB(3475txo)302019-08-31T05:53:38Z UpdateTip: new best=000000000000000014c552ced25645452a0b8632753e9288e2decedd273c5828 height=311017version=0x00000002 log2_work=79.744747 tx=42645541date='2014-07-16T14:10:17Z'progress=0.095648 cache=1.0MiB(7067txo)312019-08-31T05:53:40Z UpdateTip: new best=0000000000000000260ef522f4875fb0d5207e4e3ac97ce373a47209bcee52b6 height=311018version=0x00000002 log2_work=79.744853 tx=42645990date='2014-07-16T14:18:18Z'progress=0.095649 cache=1.2MiB(8621txo)322019-08-31T05:53:42Z UpdateTip: new best=0000000000000000007dabdebadfde7beaef31d13133600d0d88695146e2fac6 height=311019version=0x00000002 log2_work=79.744959 tx=42646068date='2014-07-16T14:19:50Z'progress=0.095649 cache=1.2MiB(8821txo)332019-08-31T05:53:45Z UpdateTip: new best=00000000000000001fc78d459e2480177ceea92d53f75cdbd856501b60cbdc3a height=311020version=0x00000002 log2_work=79.745065 tx=42646933date='2014-07-16T14:34:32Z'progress=0.095651 cache=1.6MiB(11938txo)34< snip >
352019-08-31T06:00:41Z UpdateTip: new best=000000000000000017de2992c0de3e98d711253582fa7ee626645e395e4fd0e5 height=311697version=0x00000002 log2_work=79.815121 tx=42899222date='2014-07-20T16:20:21Z'progress=0.096217 cache=67.4MiB(497634txo)362019-08-31T06:00:44Z UpdateTip: new best=000000000000000022aeedbb76913a3666d997897c23efc8e92fe38ec79728a7 height=311698version=0x00000002 log2_work=79.815222 tx=42899470date='2014-07-20T16:25:14Z'progress=0.096217 cache=68.0MiB(502949txo)372019-08-31T06:00:47Z UpdateTip: new best=000000000000000027a68e70c9c02985173c56e8c8ce210c02eb975530d77f0d height=311699version=0x00000002 log2_work=79.815323 tx=42899561date='2014-07-20T16:27:06Z'progress=0.096218 cache=68.3MiB(505709txo)382019-08-31T06:00:51Z UpdateTip: new best=000000000000000038730cd937f594452e96b97a496afc03a84fc90a18119113 height=311700version=0x00000002 log2_work=79.815424 tx=42900165date='2014-07-20T16:40:48Z'progress=0.096219 cache=68.8MiB(509386txo)
naumenkogs
commented at 5:04 pm on September 3, 2019:
member
Concept ACK on adding more redundancy.
Agree that Tor support is desirable, and also measures suggested by @practicalswift are important, but this feature even before those measures is already a big improvement (without trading any privacy comparing to the current threat model with unencrypted p2p I believe).
MarcoFalke referenced this in commit
8e00a68552
on Sep 3, 2019
sidhujag referenced this in commit
b3459434c9
on Sep 3, 2019
laanwj
commented at 9:15 am on September 4, 2019:
member
Concept ACK!
elichai
commented at 6:47 am on September 5, 2019:
contributor
Could we try and use something like https://github.com/dtolnay/no-panic on parts of the code? (if we can, this will give us compile time guarantees of no panics)
Other than that I like this and would love to review it when it’s reviewable :)
TheBlueMatt
commented at 4:53 pm on September 5, 2019:
member
I’d rather deliberately use panics so that we can enable overflow checking and catch the panics to kill the Rust thread(s) but leave the rest of Core running. Good call on NonNull, will update to use that!
TheBlueMatt force-pushed
on Sep 6, 2019
TheBlueMatt force-pushed
on Sep 6, 2019
TheBlueMatt force-pushed
on Sep 6, 2019
TheBlueMatt force-pushed
on Sep 6, 2019
TheBlueMatt marked this as ready for review
on Sep 6, 2019
TheBlueMatt
commented at 7:19 pm on September 6, 2019:
member
Aside from the final commit working around one last build issue, I believe this is ready for review. Doesn’t make sense to land for 19, but would be nice to land early in the cycle for 20.
TheBlueMatt force-pushed
on Sep 6, 2019
theuni
commented at 8:53 pm on September 6, 2019:
member
I’m taking a look at a proper fix for the circular dependency.
TheBlueMatt force-pushed
on Sep 6, 2019
practicalswift
commented at 5:13 am on September 7, 2019:
contributor
TLS support would be more or less free if we didn’t roll our own implementation? :-)
TLS would be really nice to have since our goal with this PR is to increase censorship resistance.
fanquake added this to the milestone 0.20.0
on Sep 7, 2019
DrahtBot added the label
Needs rebase
on Sep 7, 2019
TheBlueMatt force-pushed
on Sep 7, 2019
TheBlueMatt
commented at 5:33 pm on September 7, 2019:
member
Rebased.
Yea, probably makes sense to switch to a non-handrolled-HTTP-parser eventually, but:
a) I haven’t yet had the time to look into existing rust ones to see if I can find anything suitable (ie doesn’t pull in a million dependencies, implying its probably not async/tokio based, and easy to review), which in my previous experience implies this may be hard,
b) if we add any dependencies we have to have a process for vendoring the entire recursive dependency tree, which is gonna be its own hurdle, so I figured leave that for a follow-up PR.
DrahtBot removed the label
Needs rebase
on Sep 7, 2019
TheBlueMatt
commented at 8:43 pm on September 8, 2019:
Cause I didn’t know CStr existed :p
in
src/rusty/src/rest_downloader.rs:212
in
14bc05537foutdated
207+
208+#[no_mangle]
209+pub extern "C" fn init_fetch_rest_blocks(uri: *const u8) -> bool {
210+ let mut uri_vec = Vec::with_capacity(50);
211+ for i in 0..10000 {
212+ let c = unsafe { *uri.offset(i) };
elichai
commented at 9:28 pm on September 7, 2019:
A. I’m not sure dereferencing a char* casted to *const u8, is safe.
B. if you pass this as *const c_char and then use rust’s CStr (as I wrote above) you can replace these ~10 lines with:
in
src/rusty/src/rest_downloader.rs:31
in
14bc05537foutdated
22+ host_path = &host_path[1..];
23+ }
24+ let mut host_path_iter = host_path.splitn(2, "/");
25+ let (host_port_len, host, port) = match host_path_iter.next() {
26+ Some(r) if !r.is_empty() => {
27+ let is_v6_explicit = !r.is_empty() && r.as_bytes()[0] == '[' as u8;
elichai
commented at 9:52 pm on September 7, 2019:
Same, unless we have something that if !uri.is_ascii() return None; at the start of the function we should really try and not index into strings
elichai
commented at 9:54 pm on September 7, 2019:
and btw you can do b'[' instead of '[' as u8 :)
in
src/rusty/src/rest_downloader.rs:231
in
14bc05537foutdated
220+ // Sadly only non-SSL is supported for now
221+ if let Some((false, _, _, _)) = split_uri(&uri_str) { } else { return false; }
222+ std::thread::spawn(move || {
223+ // Always catch panics so that even if we have some bug in our parser we don't take the
224+ // rest of Bitcoin Core down with us:
225+ let _ = catch_unwind(move || {
elichai
commented at 10:03 pm on September 7, 2019:
Could we easily log a panic easily somehow? (although this introduces a lot of complications to pass the datadir location somehow, could we maybe use some tmp location just as a jump start?)
TheBlueMatt
commented at 3:04 am on September 9, 2019:
Right, it would be really nice to be able to call LogPrintf from rust code, but I’d prefer to leave that to a future PR.
in
src/rusty/src/rest_downloader.rs:226
in
14bc05537foutdated
216+ let uri_str = match String::from_utf8(uri_vec) {
217+ Ok(r) => r,
218+ Err(_) => return false,
219+ };
220+ // Sadly only non-SSL is supported for now
221+ if let Some((false, _, _, _)) = split_uri(&uri_str) { } else { return false; }
elichai
commented at 10:06 pm on September 7, 2019:
I think this should be reversed to check if SSL is true.
Because if this returns None we might as well also return false and finish this early, because we unwrap this few lines after
Better yet, run it once and check for if ssl {return False;} so that we won’t need to run this twice(not that it really matters that much…)
TheBlueMatt
commented at 3:03 am on September 9, 2019:
Hmm? The pattern hers is if let Some() {} else { return; }. It reads a bit weird but its the easiest way to write it out.
in
src/init.cpp:375
in
14bc05537foutdated
370@@ -367,6 +371,9 @@ void SetupServerArgs()
371 #endif
372 gArgs.AddArg("-blockreconstructionextratxn=<n>", strprintf("Extra transactions to keep in memory for compact block reconstructions (default: %u)", DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
373 gArgs.AddArg("-blocksonly", strprintf("Whether to reject transactions from network peers. Transactions from the wallet, RPC and relay whitelisted inbound peers are not affected. (default: %u)", DEFAULT_BLOCKSONLY), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
374+#if ENABLE_RUSTY
375+ gArgs.AddArg("-blockfetchrest=<uri>", "A REST endpoint from which to fetch blocks. Acts as a redundant backup for P2P connectivity", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
elichai
commented at 10:18 pm on September 7, 2019:
maybe add an example of how the uri should be formatted? (especially because currently there’s no feedback from split_uri)
TheBlueMatt
commented at 3:02 am on September 9, 2019:
I went ahead and added the deanonymizingseed.com one, if folks complain I can use example.com.
in
src/rusty/src/rest_downloader.rs:243
in
14bc05537foutdated
elichai
commented at 10:31 pm on September 7, 2019:
Ideally we would match against the exact error match so that if it returns something like InvalidData then there’s no need to keep the loop running. (so stop unless it’s a timeout, broken pipe, would block etc.)
TheBlueMatt
commented at 3:00 am on September 9, 2019:
Ehh, I’d rather keep polling. Better to keep polling so that when the rest endpoint fixes their misconfiguration (eg its returning a 500 or 404 or whatever) the downloader picks back up.
in
src/rusty/src/rest_downloader.rs:274
in
14bc05537foutdated
263+ // We got exactly the header we requested, ie it is *also* the tip for the
264+ // remote node, go on to block fetching!
265+ break 'header_sync;
266+ } else if headers.len() == 0 {
267+ let genesis_tip = BlockIndex::genesis();
268+ if genesis_tip == provider_state.get_current_best() { // Maybe they're on a different network entirely?
elichai
commented at 10:40 pm on September 7, 2019:
Add a comment that this should only ever trip on the second connection?
TheBlueMatt
commented at 2:59 am on September 9, 2019:
I mean that seems pretty obvious given the code?
in
src/rusty/src/rest_downloader.rs:275
in
14bc05537foutdated
264+ // remote node, go on to block fetching!
265+ break 'header_sync;
266+ } else if headers.len() == 0 {
267+ let genesis_tip = BlockIndex::genesis();
268+ if genesis_tip == provider_state.get_current_best() { // Maybe they're on a different network entirely?
269+ continue 'reconnect;
elichai
commented at 10:41 pm on September 7, 2019:
If we’re on completely separate chains why reconnect?
TheBlueMatt
commented at 2:58 am on September 9, 2019:
The server may also be broken and be returning empty responses, so best to keep trying.
in
src/rusty/src/bridge.rs:105
in
14bc05537foutdated
elichai
commented at 3:04 pm on September 9, 2019:
Great catch :)
that way we won’t have a dangling pointer at some point
TheBlueMatt force-pushed
on Sep 9, 2019
TheBlueMatt force-pushed
on Sep 28, 2019
laanwj added the label
Feature
on Sep 30, 2019
TheBlueMatt force-pushed
on Sep 30, 2019
TheBlueMatt
commented at 11:57 pm on September 30, 2019:
member
Now based on #16834 instead of the other way around, but otherwise this should be mostly good to go!
TheBlueMatt force-pushed
on Oct 6, 2019
TheBlueMatt force-pushed
on Oct 7, 2019
DrahtBot added the label
Needs rebase
on Oct 9, 2019
TheBlueMatt force-pushed
on Oct 10, 2019
TheBlueMatt force-pushed
on Oct 16, 2019
TheBlueMatt force-pushed
on Oct 16, 2019
DrahtBot removed the label
Needs rebase
on Oct 16, 2019
DrahtBot added the label
Needs rebase
on Oct 26, 2019
TheBlueMatt force-pushed
on Oct 26, 2019
DrahtBot removed the label
Needs rebase
on Oct 26, 2019
TheBlueMatt force-pushed
on Oct 29, 2019
TheBlueMatt force-pushed
on Nov 3, 2019
TheBlueMatt force-pushed
on Nov 3, 2019
TheBlueMatt force-pushed
on Nov 3, 2019
DrahtBot added the label
Needs rebase
on Nov 8, 2019
TheBlueMatt force-pushed
on Nov 12, 2019
DrahtBot removed the label
Needs rebase
on Nov 12, 2019
DrahtBot added the label
Needs rebase
on Nov 19, 2019
TheBlueMatt force-pushed
on Nov 19, 2019
DrahtBot removed the label
Needs rebase
on Nov 20, 2019
DrahtBot added the label
Needs rebase
on Nov 20, 2019
TheBlueMatt force-pushed
on Nov 21, 2019
DrahtBot removed the label
Needs rebase
on Nov 21, 2019
DrahtBot added the label
Needs rebase
on Dec 4, 2019
Adds a rust library to bitcoin to demonstrate linking and building rust code.
The demonstration library compiles a rust hello world example and auto-generates
a header which can be included in C++ code.
Co-Authored-By: Jeremy Rubin <j@rubin.io>
Co-Authored-By: Cory Fields <cory-nospam-@coryfields.com>
Various changes by: Matt Corallo <git@bluematt.me>
100ce28f5a
build: show rust enabled in configure output4830d9e0c8
build: gitignore src/rusty_test828a9822a0
Add basic ffi bindings for Rust header download
Also, break circular dependency with a new helper lib courtesy of
Cory Fields <cory-nospam-@coryfields.com>.
9bd5f6fba0
Add headers-over-DNS fetcher in Rustf0763b28ea
Limit total memory allocated by all Rust code to 128MBeb21b69810
Enable rustc building + testing on xenial Tsan Travis job94051addd9
Move CNode's FindNextBlocksToDownload state into its own strut
This starts the process of moving the last bits of
validation-critical logic out of net_processing - the fallback
logic of which blocks to download is incredibly critical to
validation and would likely also be used for any parallel block
sync systems. Further, assumeutxo will require additional ability
to select blocks for download, which is a validation-specific
concept and shouldn't really live in net_processing.
This moves a few responsibilities to the FindNextBlocksToDownload
callsite instead of passing in a CNodeId, but otherwise has no
functional changes.
ccbd928cf5
Make FindNextBlocksToDownload a member func on BlockProviderState0696ab1bab
Make FindNextBlocksToDownload not use mapBlockIndex for in-progress
This makes it more general than just net_processing
6fc556d1f8
Move BlockProvider to validation.{h,cpp} from net_processinge513835e20
Add ffis to access BlockProviderState and hand blocks to C++1361107c89
Add a rust-based backup over-REST block downloader2c0dda33c5
TheBlueMatt force-pushed
on Dec 5, 2019
DrahtBot removed the label
Needs rebase
on Dec 5, 2019
DrahtBot
commented at 11:43 pm on January 7, 2020:
member
DrahtBot added the label
Needs rebase
on Jan 7, 2020
luke-jr
commented at 5:08 am on January 18, 2020:
member
would be nice to land early in the cycle for 20.
Rust is still a concept NACK…
TheBlueMatt
commented at 7:48 pm on March 5, 2020:
member
Closing due to lack of interest.
TheBlueMatt closed this
on Mar 5, 2020
humbleDasher referenced this in commit
2996f593ef
on Nov 13, 2021
pravblockc referenced this in commit
0b4f279949
on Nov 18, 2021
This is a metadata mirror of the GitHub repository
bitcoin/bitcoin.
This site is not affiliated with GitHub.
Content is generated from a GitHub metadata backup.
generated: 2024-11-21 15:12 UTC
This site is hosted by @0xB10C More mirrored repositories can be found on mirror.b10c.me