Skip to content

Commit

Permalink
Make wallet communicate with index via RPC (ordinals#2929)
Browse files Browse the repository at this point in the history
  • Loading branch information
raphjaph authored Jan 23, 2024
1 parent 4b95ff6 commit 08b6380
Show file tree
Hide file tree
Showing 60 changed files with 2,918 additions and 2,277 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ mp4 = "0.14.0"
ord-bitcoincore-rpc = "0.17.1"
redb = "1.5.0"
regex = "1.6.0"
reqwest = { version = "0.11.23", features = ["blocking", "json"] }
rss = "2.0.1"
rust-embed = "8.0.0"
rustls = "0.22.0"
Expand Down
4 changes: 0 additions & 4 deletions docs/src/guides/explorer.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@ To enable the JSON-API endpoints add the `--enable-json-api` or `-j` flag (see

`ord server --enable-json-api`

To test how your inscriptions will look you can run:

`ord preview <FILE1> <FILE2> ...`

Search
------

Expand Down
3 changes: 0 additions & 3 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,6 @@ update-changelog:
echo >> CHANGELOG.md
git log --pretty='format:- %s' >> CHANGELOG.md

preview-examples:
cargo run preview examples/*

convert-logo-to-favicon:
convert -background none -resize 256x256 logo.svg static/favicon.png

Expand Down
113 changes: 3 additions & 110 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use {
TableDefinition, TableHandle, TableStats, WriteTransaction,
},
std::{
collections::{BTreeSet, HashMap},
collections::HashMap,
io::{BufWriter, Write},
sync::{Mutex, Once},
},
Expand Down Expand Up @@ -174,7 +174,7 @@ pub(crate) struct InscriptionInfo {
pub(crate) charms: u16,
}

trait BitcoinCoreRpcResultExt<T> {
pub(crate) trait BitcoinCoreRpcResultExt<T> {
fn into_option(self) -> Result<Option<T>>;
}

Expand Down Expand Up @@ -417,20 +417,6 @@ impl Index {
self.durability = durability;
}

pub(crate) fn check_sync(&self, utxos: &BTreeMap<OutPoint, Amount>) -> Result<bool> {
let rtx = self.database.begin_read()?;
let outpoint_to_value = rtx.open_table(OUTPOINT_TO_VALUE)?;
for outpoint in utxos.keys() {
if outpoint_to_value.get(&outpoint.store())?.is_none() {
return Err(anyhow!(
"output in Bitcoin Core wallet but not in ord index: {outpoint}"
));
}
}

Ok(true)
}

pub(crate) fn contains_output(&self, output: &OutPoint) -> Result<bool> {
Ok(
self
Expand Down Expand Up @@ -858,32 +844,6 @@ impl Index {
Ok(entries)
}

pub(crate) fn get_rune_balance(&self, outpoint: OutPoint, id: RuneId) -> Result<u128> {
let rtx = self.database.begin_read()?;

let outpoint_to_balances = rtx.open_table(OUTPOINT_TO_RUNE_BALANCES)?;

let Some(balances) = outpoint_to_balances.get(&outpoint.store())? else {
return Ok(0);
};

let balances_buffer = balances.value();

let mut i = 0;
while i < balances_buffer.len() {
let (balance_id, length) = runes::varint::decode(&balances_buffer[i..]);
i += length;
let (amount, length) = runes::varint::decode(&balances_buffer[i..]);
i += length;

if RuneId::try_from(balance_id).unwrap() == id {
return Ok(amount);
}
}

Ok(0)
}

pub(crate) fn get_rune_balances_for_outpoint(
&self,
outpoint: OutPoint,
Expand Down Expand Up @@ -925,22 +885,6 @@ impl Index {
Ok(balances)
}

pub(crate) fn get_runic_outputs(&self, outpoints: &[OutPoint]) -> Result<BTreeSet<OutPoint>> {
let rtx = self.database.begin_read()?;

let outpoint_to_balances = rtx.open_table(OUTPOINT_TO_RUNE_BALANCES)?;

let mut runic = BTreeSet::new();

for outpoint in outpoints {
if outpoint_to_balances.get(&outpoint.store())?.is_some() {
runic.insert(*outpoint);
}
}

Ok(runic)
}

pub(crate) fn get_rune_balance_map(&self) -> Result<BTreeMap<Rune, BTreeMap<OutPoint, u128>>> {
let outpoint_balances = self.get_rune_balances()?;

Expand Down Expand Up @@ -1575,28 +1519,6 @@ impl Index {
))
}

pub(crate) fn get_inscriptions(
&self,
utxos: &BTreeMap<OutPoint, Amount>,
) -> Result<BTreeMap<SatPoint, InscriptionId>> {
let rtx = self.database.begin_read()?;

let mut result = BTreeMap::new();

let satpoint_to_sequence_number = rtx.open_multimap_table(SATPOINT_TO_SEQUENCE_NUMBER)?;
let sequence_number_to_inscription_entry =
rtx.open_table(SEQUENCE_NUMBER_TO_INSCRIPTION_ENTRY)?;
for utxo in utxos.keys() {
result.extend(Self::inscriptions_on_output(
&satpoint_to_sequence_number,
&sequence_number_to_inscription_entry,
*utxo,
)?);
}

Ok(result)
}

pub(crate) fn get_inscriptions_paginated(
&self,
page_size: u32,
Expand Down Expand Up @@ -2036,11 +1958,7 @@ impl Index {

#[cfg(test)]
mod tests {
use {
super::*,
crate::index::testing::Context,
bitcoin::secp256k1::rand::{self, RngCore},
};
use {super::*, crate::index::testing::Context};

#[test]
fn height_limit() {
Expand Down Expand Up @@ -3339,31 +3257,6 @@ mod tests {
}
}

#[test]
fn unsynced_index_fails() {
for context in Context::configurations() {
let mut entropy = [0; 16];
rand::thread_rng().fill_bytes(&mut entropy);
let mnemonic = Mnemonic::from_entropy(&entropy).unwrap();
crate::subcommand::wallet::initialize("ord".into(), &context.options, mnemonic.to_seed(""))
.unwrap();
context.rpc_server.mine_blocks(1);
assert_regex_match!(
crate::subcommand::wallet::get_unspent_outputs(
&crate::subcommand::wallet::bitcoin_rpc_client_for_wallet_command(
"ord".to_string(),
&context.options,
)
.unwrap(),
&context.index
)
.unwrap_err()
.to_string(),
r"output in Bitcoin Core wallet but not in ord index: [[:xdigit:]]{64}:\d+"
);
}
}

#[test]
fn unrecognized_even_field_inscriptions_are_cursed_and_unbound() {
for context in Context::configurations() {
Expand Down
4 changes: 1 addition & 3 deletions src/index/testing.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::*;
use {super::*, std::ffi::OsString, tempfile::TempDir};

pub(crate) struct ContextBuilder {
args: Vec<OsString>,
Expand Down Expand Up @@ -36,7 +36,6 @@ impl ContextBuilder {
index.update().unwrap();

Ok(Context {
options,
rpc_server,
tempdir,
index,
Expand Down Expand Up @@ -65,7 +64,6 @@ impl ContextBuilder {
}

pub(crate) struct Context {
pub(crate) options: Options,
pub(crate) rpc_server: test_bitcoincore_rpc::Handle,
#[allow(unused)]
pub(crate) tempdir: TempDir,
Expand Down
34 changes: 23 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#![allow(
clippy::large_enum_variant,
clippy::result_large_err,
clippy::too_many_arguments,
clippy::type_complexity,
clippy::result_large_err
clippy::type_complexity
)]
#![deny(
clippy::cast_lossless,
Expand Down Expand Up @@ -59,15 +60,14 @@ use {
cmp,
collections::{BTreeMap, BTreeSet, HashMap, HashSet, VecDeque},
env,
ffi::OsString,
fmt::{self, Display, Formatter},
fs::{self, File},
io::{self, Cursor},
mem,
net::{TcpListener, ToSocketAddrs},
net::ToSocketAddrs,
ops::{Add, AddAssign, Sub},
path::{Path, PathBuf},
process::{self, Command},
process,
str::FromStr,
sync::{
atomic::{self, AtomicBool},
Expand All @@ -77,7 +77,7 @@ use {
time::{Duration, Instant, SystemTime},
},
sysinfo::System,
tempfile::TempDir,
templates::{InscriptionJson, OutputJson, RuneJson, StatusJson},
tokio::{runtime::Runtime, task},
};

Expand All @@ -92,7 +92,7 @@ pub use self::{
runes::{Edict, Rune, RuneId, Runestone},
sat::Sat,
sat_point::SatPoint,
subcommand::wallet::transaction_builder::{Target, TransactionBuilder},
wallet::transaction_builder::{Target, TransactionBuilder},
};

#[cfg(test)]
Expand All @@ -112,7 +112,7 @@ macro_rules! tprintln {
};
}

mod arguments;
pub mod arguments;
mod blocktime;
pub mod chain;
mod config;
Expand All @@ -123,7 +123,7 @@ mod deserialize_from_str;
mod epoch;
mod fee_rate;
mod height;
mod index;
pub mod index;
mod inscriptions;
mod object;
mod options;
Expand All @@ -137,6 +137,7 @@ mod server_config;
pub mod subcommand;
mod tally;
pub mod templates;
pub mod wallet;

type Result<T = (), E = Error> = std::result::Result<T, E>;

Expand Down Expand Up @@ -200,6 +201,16 @@ fn unbound_outpoint() -> OutPoint {
}
}

pub fn parse_ord_server_args(args: &str) -> (Options, crate::subcommand::server::Server) {
match Arguments::try_parse_from(args.split_whitespace()) {
Ok(arguments) => match arguments.subcommand {
Subcommand::Server(server) => (arguments.options, server),
subcommand => panic!("unexpected subcommand: {subcommand:?}"),
},
Err(err) => panic!("error parsing arguments: {err}"),
}
}

fn gracefully_shutdown_indexer() {
if let Some(indexer) = INDEXER.lock().unwrap().take() {
// We explicitly set this to true to notify the thread to not take on new work
Expand All @@ -226,6 +237,8 @@ pub fn main() {
.unwrap()
.iter()
.for_each(|handle| handle.graceful_shutdown(Some(Duration::from_millis(100))));

gracefully_shutdown_indexer();
})
.expect("Error setting <CTRL-C> handler");

Expand All @@ -251,8 +264,7 @@ pub fn main() {
if let Some(output) = output {
output.print_json();
}
gracefully_shutdown_indexer();
}
}

gracefully_shutdown_indexer();
}
4 changes: 2 additions & 2 deletions src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ impl Options {

#[cfg(test)]
mod tests {
use {super::*, bitcoin::Network, std::path::Path};
use {super::*, bitcoin::Network, std::path::Path, tempfile::TempDir};

#[test]
fn rpc_url_overrides_network() {
Expand Down Expand Up @@ -569,7 +569,7 @@ mod tests {
);
}

fn parse_wallet_args(args: &str) -> (Options, subcommand::wallet::Wallet) {
fn parse_wallet_args(args: &str) -> (Options, subcommand::wallet::WalletCommand) {
match Arguments::try_parse_from(args.split_whitespace()) {
Ok(arguments) => match arguments.subcommand {
Subcommand::Wallet(wallet) => (arguments.options, wallet),
Expand Down
9 changes: 5 additions & 4 deletions src/runes/pile.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use super::*;

pub(crate) struct Pile {
pub(crate) amount: u128,
pub(crate) divisibility: u8,
pub(crate) symbol: Option<char>,
#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Pile {
pub amount: u128,
pub divisibility: u8,
pub symbol: Option<char>,
}

impl Display for Pile {
Expand Down
Loading

0 comments on commit 08b6380

Please sign in to comment.