Skip to content

Commit

Permalink
Implement new REST API: GET /colors/
Browse files Browse the repository at this point in the history
  • Loading branch information
Yamaguchi committed Mar 14, 2024
1 parent d5140e9 commit ef4a407
Show file tree
Hide file tree
Showing 9 changed files with 833 additions and 611 deletions.
1,337 changes: 730 additions & 607 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ page_size = "0.4.2"
prometheus = "0.11.0"
openassets-tapyrus = "^0.2.4"
rayon = "1.5.0"
rocksdb = { version = "0.15.0", optional = true }
rocksdb-oldcpu = { version = "0.12.4", optional = true, package = "rocksdb" }
rocksdb = { version = "^0.22.0", optional = true }
rocksdb-oldcpu = { version = "^0.22.0", optional = true, package = "rocksdb" }
rust-crypto = "0.2"
serde = { version = "1.0.118", features = ["derive"] }
serde_derive = "1.0.118"
Expand Down
7 changes: 7 additions & 0 deletions doc/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,13 @@ For example: `{ "1": 87.882, "2": 87.882, "3": 87.882, "4": 87.882, "5": 81.129,

## Tokens

### `GET /colors[/:last_seen_color_id]`

Returns a list of the 25 `color_id`s

if `last_seen_color_id` specified, returns a list of the next 25 `color_id`s after specified `last_seen_color_id`


### `GET /color/:color_id`

Get information about a colored coin.
Expand Down
3 changes: 3 additions & 0 deletions doc/schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ Each output results in the following new row:

* `"O{txid}{vout}" → "{scriptpubkey}{value}"`

If transaction output include colored coins, it results in the following new row:
* `c{color_id}` -> ""`

When the indexer is synced up to the tip of the chain, the hash of the tip is saved as following:

* `"t" → "{blockhash}"`
Expand Down
2 changes: 1 addition & 1 deletion src/new_index/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ impl ColoredStatsCacheRow {
}
}

#[derive(Serialize, Deserialize, Debug)]
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ColoredStats {
pub color_id: ColorIdentifier,
pub tx_count: usize,
Expand Down
2 changes: 1 addition & 1 deletion src/new_index/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ impl<'a> Iterator for ScanIterator<'a> {
if self.done {
return None;
}
let (key, value) = self.iter.next()?;
let (key, value) = self.iter.next()?.ok()?;
if !key.starts_with(&self.prefix) {
self.done = true;
return None;
Expand Down
8 changes: 8 additions & 0 deletions src/new_index/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,14 @@ impl Query {
Ok(map)
}

pub fn get_colors(&self, last_seen_color_id: Option<ColorIdentifier>, limit: usize) -> Vec<ColorIdentifier> {
let colors = self
.chain
.get_colors(last_seen_color_id, limit)
.expect("failed to get colors");
colors
}

pub fn get_colored_stats(&self, color_id: &ColorIdentifier) -> (ColoredStats, ColoredStats) {
(
self.chain
Expand Down
72 changes: 72 additions & 0 deletions src/new_index/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ use crate::util::{
use crate::new_index::db::{DBFlush, DBRow, ReverseScanIterator, ScanIterator, DB};
use crate::new_index::fetch::{start_fetcher, BlockEntry, FetchFrom};

use super::color::{deserialize_color_id, serialize_color_id};

const MIN_HISTORY_ITEMS_TO_CACHE: usize = 100;

pub struct Store {
Expand Down Expand Up @@ -674,6 +676,30 @@ impl ChainQuery {
update_stats(init_stats, &histories)
}

pub fn get_colors(&self, last_seen_color_id: Option<ColorIdentifier>, limit: usize) -> Result<Vec<ColorIdentifier>> {
let colors: Vec<ColorIdentifier> = self
.store
.txstore_db()
.iter_scan(&ColorIdRow::prefix())
.map(|row|{
ColorIdRow::from_row(row)
})
.map(|row| {
row.key.color_id
})
.skip_while(|color_id| {
// skip until we reach the last_seen_color_id
last_seen_color_id.clone().map_or(false, |last_seen_color_id| last_seen_color_id != color_id.clone())
})
.skip(match last_seen_color_id {
Some(_) => 1, // skip the last_seen_color_id itself
None => 0,
})
.take(limit)
.collect();
Ok(colors)
}

pub fn get_colored_stats(&self, color_id: &ColorIdentifier) -> Result<ColoredStats> {
let cache: Option<(ColoredStats, usize)> = self
.store
Expand Down Expand Up @@ -1018,6 +1044,10 @@ fn add_transaction(
if is_spendable(txo) {
rows.push(TxOutRow::new(&txid, txo_index, txo).into_row());
}

if let Some((color_id, _)) = txo.script_pubkey.split_color() {
rows.push(ColorIdRow::new(&color_id).into_row())
}
}
}

Expand Down Expand Up @@ -1330,6 +1360,48 @@ impl TxOutRow {
}
}

#[derive(Serialize, Deserialize)]
struct ColorIdKey {
code: u8,
color_id: ColorIdentifier,
}
struct ColorIdRow {
key: ColorIdKey,
}

impl ColorIdRow {
fn new(color_id: &ColorIdentifier) -> ColorIdRow {
ColorIdRow {
key: ColorIdKey {
code: b'c',
color_id: color_id.clone()
}
}
}

fn prefix() -> Bytes {
b"c".to_vec()
}

fn into_row(self) -> DBRow {
DBRow {
key: bincode::serialize(&(b'c', &serialize_color_id(&self.key.color_id))).unwrap(),
value: vec![],
}
}
fn from_row(row: DBRow) -> Self {
let (_prefix, token_type, payload): (u8, u8, [u8; 32]) =
bincode::deserialize(&row.key).expect("failed to deserialize ColorIdRow");
ColorIdRow {
key: ColorIdKey {
code: b'c',
color_id: deserialize_color_id(token_type, payload),
}
}
}
}


#[derive(Serialize, Deserialize)]
struct BlockKey {
code: u8,
Expand Down
9 changes: 9 additions & 0 deletions src/rest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const MAX_MEMPOOL_TXS: usize = 50;
const MEMPOOL_TXS_PER_PAGE: usize = 25;
const BLOCK_LIMIT: usize = 10;
const ADDRESS_SEARCH_LIMIT: usize = 10;
const COLOR_IDS_PER_PAGE: usize = 25;

const TTL_LONG: u32 = 157_784_630; // ttl for static resources (5 years)
const TTL_SHORT: u32 = 10; // ttl for volatie resources
Expand Down Expand Up @@ -907,6 +908,14 @@ fn handle_request(
.unwrap())
}

(&Method::GET, Some(&"colors"), last_seen_color_id, None, None, None) => {
let color_id: Option<ColorIdentifier> = last_seen_color_id.map_or(None,|hex| {
ColorIdentifier::from_hex(hex).ok()
});
let colors: Vec<ColorIdentifier> = query.get_colors(color_id, COLOR_IDS_PER_PAGE);
json_response(colors, TTL_SHORT)
}

(&Method::GET, Some(&"color"), Some(color_id), None, None, None) => {
let color_id = ColorIdentifier::from_hex(color_id).unwrap();
let stats = query.get_colored_stats(&color_id);
Expand Down

0 comments on commit ef4a407

Please sign in to comment.