Skip to content

Commit 24e2997

Browse files
authored
Ocean: block indexing (#2777)
* experimental_allow_proto3_optional * ffi blockv2info * update ocean block apis * pindex->stakeModifier * rm block.reward * add missing column block_by_height * rm unuse
1 parent e453a3e commit 24e2997

9 files changed

Lines changed: 156 additions & 82 deletions

File tree

lib/ain-grpc/build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ fn compile_proto_and_generate_services(
266266
// There's no way to compile protos using custom generator in tonic,
267267
// so we're left with creating a prost config and using that for codegen.
268268
let mut config = Config::new();
269+
config.protoc_arg("--experimental_allow_proto3_optional");
269270
config.out_dir(out_dir);
270271
config.service_generator(Box::new(gen));
271272
config

lib/ain-ocean/src/api/block.rs

Lines changed: 40 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,54 @@ use axum::{
33
routing::get,
44
Json, Router,
55
};
6-
use serde::{Deserialize, Serialize};
7-
8-
use crate::{api_paged_response::ApiPagedResponse, api_query::PaginationQuery, error::OceanResult};
9-
10-
#[derive(Deserialize)]
11-
struct BlockId {
12-
id: String,
13-
}
14-
15-
#[derive(Deserialize)]
16-
struct BlockHash {
17-
hash: String,
18-
}
6+
use bitcoin::BlockHash;
7+
8+
use crate::{
9+
api_paged_response::ApiPagedResponse,
10+
api_query::PaginationQuery,
11+
error::OceanResult,
12+
SERVICES,
13+
repository::RepositoryOps,
14+
model::Block,
15+
};
1916

2017
async fn list_blocks(
2118
Query(query): Query<PaginationQuery>,
2219
) -> OceanResult<Json<ApiPagedResponse<Block>>> {
23-
// TODO(): query from lvldb.. or maybe pull from index
24-
let blocks = vec![
25-
Block { id: "0".into() },
26-
Block { id: "1".into() },
27-
Block { id: "2".into() },
28-
];
29-
30-
Ok(Json(ApiPagedResponse::of(blocks, query.size, |block| {
31-
block.clone().id
32-
})))
20+
let blocks = SERVICES
21+
.block
22+
.by_height
23+
.list(None)?
24+
.take(query.size)
25+
.map(|item| {
26+
let (_, id) = item?;
27+
let b = SERVICES
28+
.block
29+
.by_id
30+
.get(&id)?
31+
.ok_or("Missing block index")?;
32+
33+
Ok(b)
34+
})
35+
.collect::<OceanResult<Vec<_>>>()?;
36+
37+
Ok(Json(ApiPagedResponse::of(
38+
blocks,
39+
query.size,
40+
|block| block.clone().id,
41+
)))
3342
}
3443

35-
async fn get_block(Path(BlockId { id }): Path<BlockId>) -> OceanResult<Json<Block>> {
36-
Ok(Json(Block { id }))
44+
async fn get_block(Path(id): Path<BlockHash>) -> OceanResult<Json<Option<Block>>> {
45+
let block = SERVICES
46+
.block
47+
.by_id
48+
.get(&id)?;
49+
50+
Ok(Json(block))
3751
}
3852

39-
async fn get_transactions(Path(BlockHash { hash }): Path<BlockHash>) -> String {
53+
async fn get_transactions(Path(hash): Path<BlockHash>) -> String {
4054
format!("Transactions for block with hash {}", hash)
4155
}
4256

@@ -46,33 +60,3 @@ pub fn router() -> Router {
4660
.route("/:id", get(get_block))
4761
.route("/:hash/transactions", get(get_transactions))
4862
}
49-
50-
#[derive(Clone, Debug, Serialize)]
51-
#[serde(default)]
52-
pub struct Block {
53-
id: String,
54-
// TODO(): type mapping
55-
// hash: H256,
56-
// previous_hash: H256,
57-
58-
// height: u64,
59-
// version: u64,
60-
// time: u64, // ---------------| block time in seconds since epoch
61-
// median_time: u64, // --------| meidan time of the past 11 block timestamps
62-
63-
// transaction_count: u64,
64-
65-
// difficulty: u64,
66-
67-
// masternode: H256,
68-
// minter: H256,
69-
// minter_block_count: u64,
70-
// reward: f64
71-
72-
// state_modifier: H256,
73-
// merkle_root: H256,
74-
75-
// size: u64,
76-
// size_stripped: u64,
77-
// weight: u64,
78-
}

lib/ain-ocean/src/indexer/mod.rs

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,64 @@ pub(crate) trait Index {
1313
use dftx_rs::{deserialize, Block, DfTx};
1414
use log::debug;
1515

16-
use crate::{model::BlockContext, Result};
16+
use crate::{
17+
model::{BlockContext, Block as BlockMapper},
18+
repository::RepositoryOps,
19+
Result,
20+
SERVICES,
21+
};
1722

18-
pub fn index_block(block: String, block_height: u32) -> Result<()> {
23+
pub struct BlockV2Info {
24+
pub height: u32,
25+
pub difficulty: u32,
26+
pub version: i32,
27+
pub median_time: i64,
28+
pub minter_block_count: u64,
29+
pub size: usize,
30+
pub size_stripped: usize,
31+
pub weight: i64,
32+
pub stake_modifier: String,
33+
pub minter: String,
34+
pub masternode: String,
35+
}
36+
37+
pub fn index_block(encoded_block: String, info: &BlockV2Info) -> Result<()> {
1938
debug!("[index_block] Indexing block...");
2039

21-
let hex = hex::decode(block)?;
40+
let hex = hex::decode(&encoded_block)?;
2241
debug!("got hex");
2342
let block = deserialize::<Block>(&hex)?;
2443
debug!("got block");
44+
let block_hash = block.block_hash();
2545
let ctx = BlockContext {
26-
height: block_height,
27-
hash: block.block_hash(),
46+
height: info.height,
47+
hash: block_hash,
2848
time: 0, // TODO
2949
median_time: 0, // TODO
3050
};
51+
let block_mapper = BlockMapper {
52+
id: block_hash.to_string(),
53+
hash: block_hash.to_string(),
54+
previous_hash: block.header.prev_blockhash.to_string(),
55+
height: info.height,
56+
version: info.version,
57+
time: block.header.time,
58+
median_time: info.median_time,
59+
transaction_count: block.txdata.len(),
60+
difficulty: info.difficulty,
61+
masternode: info.masternode.to_owned(),
62+
minter: info.minter.to_owned(),
63+
minter_block_count: info.minter_block_count,
64+
stake_modifier: info.stake_modifier.to_owned(),
65+
merkleroot: block.header.merkle_root.to_string(),
66+
size: info.size,
67+
size_stripped: info.size_stripped,
68+
weight: info.weight,
69+
};
70+
71+
SERVICES.block.raw.put(&ctx.hash, &encoded_block)?;
72+
SERVICES.block.by_id.put(&ctx.hash, &block_mapper)?;
73+
SERVICES.block.by_height.put(&ctx.height, &block_hash)?;
3174

3275
for (idx, tx) in block.txdata.into_iter().enumerate() {
3376
let bytes = tx.output[0].script_pubkey.as_bytes();
@@ -60,6 +103,6 @@ pub fn index_block(block: String, block_height: u32) -> Result<()> {
60103
Ok(())
61104
}
62105

63-
pub fn invalidate_block(block: String, block_height: u32) -> Result<()> {
106+
pub fn invalidate_block(block: String, info: &BlockV2Info) -> Result<()> {
64107
Ok(())
65108
}

lib/ain-ocean/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ mod indexer;
66
use std::{path::PathBuf, sync::Arc};
77

88
pub use api::ocean_router;
9-
pub use indexer::{index_block, invalidate_block};
9+
pub use indexer::{BlockV2Info, index_block, invalidate_block};
1010
use repository::{
1111
AuctionHistoryByHeightRepository, AuctionHistoryRepository, BlockByHeightRepository,
1212
BlockRepository, MasternodeByHeightRepository, MasternodeRepository, MasternodeStatsRepository,

lib/ain-ocean/src/model/block.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,20 @@ pub struct Block {
77
pub id: String,
88
pub hash: String,
99
pub previous_hash: String,
10-
pub height: i32,
10+
pub height: u32,
1111
pub version: i32,
12-
pub time: i32,
13-
pub median_time: i32,
14-
pub transaction_count: i32,
15-
pub difficulty: i32,
12+
pub time: u32,
13+
pub median_time: i64,
14+
pub transaction_count: usize,
15+
pub difficulty: u32,
1616
pub masternode: String,
1717
pub minter: String,
18-
pub minter_block_count: i32,
19-
pub reward: String,
18+
pub minter_block_count: u64,
2019
pub stake_modifier: String,
2120
pub merkleroot: String,
22-
pub size: i32,
23-
pub size_stripped: i32,
24-
pub weight: i32,
21+
pub size: usize,
22+
pub size_stripped: usize,
23+
pub weight: i64,
2524
}
2625

2726
#[derive(Serialize, Deserialize, Debug, Clone)]

lib/ain-ocean/src/storage/columns/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ pub use transaction_vin::*;
4141
pub use transaction_vout::*;
4242
pub use vault_auction_history::*;
4343

44-
pub const COLUMN_NAMES: [&'static str; 22] = [
44+
pub const COLUMN_NAMES: [&'static str; 23] = [
4545
block::Block::NAME,
46+
block::BlockByHeight::NAME,
4647
masternode_stats::MasternodeStats::NAME,
4748
masternode::Masternode::NAME,
4849
masternode::MasternodeByHeight::NAME,

lib/ain-rs-exports/src/lib.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,21 @@ pub mod ffi {
5252
fn ain_rs_stop_network_services(result: &mut CrossBoundaryResult);
5353
}
5454

55+
#[derive(Default)]
56+
pub struct BlockV2Info {
57+
pub height: u32,
58+
pub difficulty: u32,
59+
pub version: i32,
60+
pub median_time: i64,
61+
pub minter_block_count: u64,
62+
pub size: usize,
63+
pub size_stripped: usize,
64+
pub weight: i64,
65+
pub stake_modifier: String,
66+
pub minter: String,
67+
pub masternode: String,
68+
}
69+
5570
// ========== Block ==========
5671
#[derive(Default)]
5772
pub struct EVMBlockHeader {
@@ -336,11 +351,11 @@ pub mod ffi {
336351
raw_tx: &str,
337352
);
338353

339-
fn ocean_index_block(result: &mut CrossBoundaryResult, block: String, block_height: u32);
354+
fn ocean_index_block(result: &mut CrossBoundaryResult, block: String, info: &BlockV2Info);
340355
fn ocean_invalidate_block(
341356
result: &mut CrossBoundaryResult,
342357
block: String,
343-
block_height: u32,
358+
info: &BlockV2Info,
344359
);
345360
}
346361

lib/ain-rs-exports/src/ocean.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,25 @@
1-
use crate::ffi::CrossBoundaryResult;
1+
use crate::ffi::{BlockV2Info as BlockV2InfoFFI, CrossBoundaryResult};
2+
use ain_ocean::BlockV2Info;
23

3-
pub fn ocean_index_block(result: &mut CrossBoundaryResult, block: String, block_height: u32) {
4-
match ain_ocean::index_block(block, block_height) {
4+
// manually convert since BlockV2InfoFFI is belongs to CPP which can't impl From -> Into
5+
pub fn convert(b: &BlockV2InfoFFI) -> BlockV2Info {
6+
BlockV2Info {
7+
height: b.height,
8+
difficulty: b.difficulty,
9+
version: b.version,
10+
median_time: b.median_time,
11+
minter_block_count: b.minter_block_count,
12+
size: b.size,
13+
size_stripped: b.size_stripped,
14+
weight: b.weight,
15+
stake_modifier: b.stake_modifier.to_owned(),
16+
minter: b.minter.to_owned(),
17+
masternode: b.masternode.to_owned(),
18+
}
19+
}
20+
21+
pub fn ocean_index_block(result: &mut CrossBoundaryResult, block: String, b: &BlockV2InfoFFI) {
22+
match ain_ocean::index_block(block, &convert(b)) {
523
Ok(()) => result.ok = true,
624
Err(e) => {
725
result.ok = false;
@@ -10,8 +28,8 @@ pub fn ocean_index_block(result: &mut CrossBoundaryResult, block: String, block_
1028
}
1129
}
1230

13-
pub fn ocean_invalidate_block(result: &mut CrossBoundaryResult, block: String, block_height: u32) {
14-
match ain_ocean::invalidate_block(block, block_height) {
31+
pub fn ocean_invalidate_block(result: &mut CrossBoundaryResult, block: String, b: &BlockV2InfoFFI) {
32+
match ain_ocean::invalidate_block(block, &convert(b)) {
1533
Ok(()) => result.ok = true,
1634
Err(e) => {
1735
result.ok = false;

src/dfi/validation.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <ffi/ffiexports.h>
2222
#include <ffi/ffihelpers.h>
2323
#include <validation.h>
24+
#include <consensus/validation.h>
2425

2526
#include <boost/asio.hpp>
2627

@@ -2799,7 +2800,19 @@ Res ProcessDeFiEventFallible(const CBlock &block,
27992800
std::string serializedData = HexStr(ss.begin(), ss.end());
28002801

28012802
CrossBoundaryResult result;
2802-
ocean_index_block(result, serializedData, pindex->nHeight);
2803+
BlockV2Info info;
2804+
info.height = pindex->nHeight;
2805+
info.difficulty = pindex->nBits;
2806+
info.version = pindex->nVersion;
2807+
info.median_time = (int64_t)pindex->GetMedianTimePast();
2808+
info.minter_block_count = pindex->mintedBlocks;
2809+
info.size = GetSerializeSize(block, PROTOCOL_VERSION);
2810+
info.size_stripped = GetSerializeSize(block, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
2811+
info.weight = GetBlockWeight(block);
2812+
info.stake_modifier = pindex->stakeModifier.ToString();
2813+
info.minter = "", // mn operator address
2814+
info.masternode = "", // mn owner address
2815+
ocean_index_block(result, serializedData, info);
28032816
// if (!result.ok) {
28042817
// return Res::Err(result.reason.c_str());
28052818
// }

0 commit comments

Comments
 (0)