mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-01-11 17:53:12 +00:00
Merge 1a033af5f248d55e95625357c011645c103cc72c into 1d09afd9e004953a7218fe02d4e897cc45c67465
This commit is contained in:
commit
d34d101e30
103
Cargo.lock
generated
103
Cargo.lock
generated
@ -657,6 +657,23 @@ version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e050f626429857a27ddccb31e0aca21356bfa709c04041aefddac081a8f068a"
|
||||
|
||||
[[package]]
|
||||
name = "bedrock_client"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"const-hex",
|
||||
"ed25519-dalek",
|
||||
"futures",
|
||||
"log",
|
||||
"reqwest 0.11.27",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_with",
|
||||
"thiserror",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.3"
|
||||
@ -1046,6 +1063,18 @@ dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-hex"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3bb320cac8a0750d7f25280aa97b09c26edfe161164238ecbbb31092b079e735"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"proptest",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.9.6"
|
||||
@ -1150,6 +1179,33 @@ dependencies = [
|
||||
"cipher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curve25519-dalek"
|
||||
version = "4.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"curve25519-dalek-derive",
|
||||
"digest",
|
||||
"fiat-crypto",
|
||||
"rustc_version",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curve25519-dalek-derive"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.111",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.11"
|
||||
@ -1407,6 +1463,31 @@ dependencies = [
|
||||
"spki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ed25519"
|
||||
version = "2.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"signature",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ed25519-dalek"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9"
|
||||
dependencies = [
|
||||
"curve25519-dalek",
|
||||
"ed25519",
|
||||
"rand_core 0.6.4",
|
||||
"serde",
|
||||
"sha2",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "educe"
|
||||
version = "0.6.0"
|
||||
@ -1561,6 +1642,12 @@ dependencies = [
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fiat-crypto"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.5"
|
||||
@ -2198,6 +2285,22 @@ version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ee796ad498c8d9a1d68e477df8f754ed784ef875de1414ebdaf169f70a6a784"
|
||||
|
||||
[[package]]
|
||||
name = "indexer"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base58",
|
||||
"common",
|
||||
"futures",
|
||||
"log",
|
||||
"nssa",
|
||||
"nssa_core",
|
||||
"serde",
|
||||
"storage",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.3"
|
||||
|
||||
@ -19,7 +19,7 @@ members = [
|
||||
"integration_tests/proc_macro_test_attribute",
|
||||
"examples/program_deployment",
|
||||
"examples/program_deployment/methods",
|
||||
"examples/program_deployment/methods/guest",
|
||||
"examples/program_deployment/methods/guest", "indexer", "bedrock_client",
|
||||
]
|
||||
|
||||
[workspace.dependencies]
|
||||
@ -76,6 +76,10 @@ chrono = "0.4.41"
|
||||
borsh = "1.5.7"
|
||||
base58 = "0.2.0"
|
||||
itertools = "0.14.0"
|
||||
url = "2.5.4"
|
||||
const-hex = { default-features = false, features = ["alloc"], version = "1" }
|
||||
serde_with = { default-features = false, version = "3.14.0" }
|
||||
ed25519-dalek = { default-features = false, version = "2" }
|
||||
|
||||
rocksdb = { version = "0.24.0", default-features = false, features = [
|
||||
"snappy",
|
||||
|
||||
17
bedrock_client/Cargo.toml
Normal file
17
bedrock_client/Cargo.toml
Normal file
@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "bedrock_client"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
reqwest.workspace = true
|
||||
anyhow.workspace = true
|
||||
serde.workspace = true
|
||||
log.workspace = true
|
||||
thiserror.workspace = true
|
||||
url.workspace = true
|
||||
futures.workspace = true
|
||||
serde_json.workspace = true
|
||||
const-hex.workspace = true
|
||||
serde_with.workspace = true
|
||||
ed25519-dalek = { workspace = true, features = ["rand_core", "serde", "zeroize"] }
|
||||
174
bedrock_client/src/lib.rs
Normal file
174
bedrock_client/src/lib.rs
Normal file
@ -0,0 +1,174 @@
|
||||
//A copy of http-client from logos-blockchain
|
||||
//ToDo: replace with dependency
|
||||
|
||||
use std::{fmt::Debug, sync::Arc};
|
||||
use reqwest::{Client, ClientBuilder, RequestBuilder, StatusCode, Url};
|
||||
use serde::{Serialize, de::DeserializeOwned};
|
||||
use futures::{Stream, StreamExt as _};
|
||||
|
||||
pub mod paths;
|
||||
pub mod structs;
|
||||
|
||||
use nomos_core::{mantle::SignedMantleTx};
|
||||
|
||||
use crate::{paths::{CRYPTARCHIA_INFO, CRYPTARCHIA_LIB_STREAM, STORAGE_BLOCK}, structs::{Block, BlockInfo, info::CryptarchiaInfo}};
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("Internal server error: {0}")]
|
||||
Server(String),
|
||||
#[error("Failed to execute request: {0}")]
|
||||
Client(String),
|
||||
#[error(transparent)]
|
||||
Request(#[from] reqwest::Error),
|
||||
#[error(transparent)]
|
||||
Url(#[from] url::ParseError),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BasicAuthCredentials {
|
||||
username: String,
|
||||
password: Option<String>,
|
||||
}
|
||||
|
||||
impl BasicAuthCredentials {
|
||||
#[must_use]
|
||||
pub const fn new(username: String, password: Option<String>) -> Self {
|
||||
Self { username, password }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CommonHttpClient {
|
||||
client: Arc<Client>,
|
||||
basic_auth: Option<BasicAuthCredentials>,
|
||||
}
|
||||
|
||||
impl CommonHttpClient {
|
||||
#[must_use]
|
||||
pub fn new(basic_auth: Option<BasicAuthCredentials>) -> Self {
|
||||
let client = ClientBuilder::new()
|
||||
.build()
|
||||
.expect("Client from default settings should be able to build");
|
||||
Self {
|
||||
client: Arc::new(client),
|
||||
basic_auth,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn new_with_client(client: Client, basic_auth: Option<BasicAuthCredentials>) -> Self {
|
||||
Self {
|
||||
client: Arc::new(client),
|
||||
basic_auth,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn post<Req, Res>(&self, request_url: Url, request_body: &Req) -> Result<Res, Error>
|
||||
where
|
||||
Req: Serialize + ?Sized + Send + Sync,
|
||||
Res: DeserializeOwned + Send + Sync,
|
||||
{
|
||||
let request = self.client.post(request_url).json(request_body);
|
||||
self.execute_request::<Res>(request).await
|
||||
}
|
||||
|
||||
pub async fn get<Req, Res>(
|
||||
&self,
|
||||
request_url: Url,
|
||||
request_body: Option<&Req>,
|
||||
) -> Result<Res, Error>
|
||||
where
|
||||
Req: Serialize + ?Sized + Send + Sync,
|
||||
Res: DeserializeOwned + Send + Sync,
|
||||
{
|
||||
let mut request = self.client.get(request_url);
|
||||
if let Some(request_body) = request_body {
|
||||
request = request.json(request_body);
|
||||
}
|
||||
self.execute_request::<Res>(request).await
|
||||
}
|
||||
|
||||
async fn execute_request<Res: DeserializeOwned>(
|
||||
&self,
|
||||
mut request: RequestBuilder,
|
||||
) -> Result<Res, Error> {
|
||||
if let Some(basic_auth) = &self.basic_auth {
|
||||
request = request.basic_auth(&basic_auth.username, basic_auth.password.as_deref());
|
||||
}
|
||||
|
||||
let response = request.send().await.map_err(Error::Request)?;
|
||||
let status = response.status();
|
||||
let body = response.text().await.map_err(Error::Request)?;
|
||||
|
||||
match status {
|
||||
StatusCode::OK => serde_json::from_str(&body)
|
||||
.map_err(|e| Error::Server(format!("Failed to parse response: {e}"))),
|
||||
StatusCode::INTERNAL_SERVER_ERROR => Err(Error::Server(body)),
|
||||
_ => Err(Error::Server(format!(
|
||||
"Unexpected response [{status}]: {body}",
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_lib_stream(
|
||||
&self,
|
||||
base_url: Url,
|
||||
) -> Result<impl Stream<Item = BlockInfo>, Error> {
|
||||
let request_url = base_url
|
||||
.join(CRYPTARCHIA_LIB_STREAM.trim_start_matches('/'))
|
||||
.map_err(Error::Url)?;
|
||||
let mut request = self.client.get(request_url);
|
||||
|
||||
if let Some(basic_auth) = &self.basic_auth {
|
||||
request = request.basic_auth(&basic_auth.username, basic_auth.password.as_deref());
|
||||
}
|
||||
|
||||
let response = request.send().await.map_err(Error::Request)?;
|
||||
let status = response.status();
|
||||
|
||||
let lib_stream = response.bytes_stream().filter_map(async |item| {
|
||||
let bytes = item.ok()?;
|
||||
serde_json::from_slice::<BlockInfo>(&bytes).ok()
|
||||
});
|
||||
match status {
|
||||
StatusCode::OK => Ok(lib_stream),
|
||||
StatusCode::INTERNAL_SERVER_ERROR => Err(Error::Server("Error".to_owned())),
|
||||
_ => Err(Error::Server(format!("Unexpected response [{status}]",))),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_block_by_id<HeaderId>(
|
||||
&self,
|
||||
base_url: Url,
|
||||
header_id: HeaderId,
|
||||
) -> Result<Option<Block<SignedMantleTx>>, Error>
|
||||
where
|
||||
HeaderId: Serialize + Send + Sync,
|
||||
{
|
||||
let request_url = base_url
|
||||
.join(STORAGE_BLOCK.trim_start_matches('/'))
|
||||
.map_err(Error::Url)?;
|
||||
self.post(request_url, &header_id).await
|
||||
}
|
||||
|
||||
/// Get consensus info (tip, height, etc.)
|
||||
pub async fn consensus_info(&self, base_url: Url) -> Result<CryptarchiaInfo, Error> {
|
||||
let request_url = base_url
|
||||
.join(CRYPTARCHIA_INFO.trim_start_matches('/'))
|
||||
.map_err(Error::Url)?;
|
||||
self.get::<(), CryptarchiaInfo>(request_url, None).await
|
||||
}
|
||||
|
||||
/// Get a block by its header ID
|
||||
pub async fn get_block(
|
||||
&self,
|
||||
base_url: Url,
|
||||
header_id: HeaderId,
|
||||
) -> Result<Option<Block<SignedMantleTx>>, Error> {
|
||||
let request_url = base_url
|
||||
.join(STORAGE_BLOCK.trim_start_matches('/'))
|
||||
.map_err(Error::Url)?;
|
||||
self.post(request_url, &header_id).await
|
||||
}
|
||||
}
|
||||
6
bedrock_client/src/paths.rs
Normal file
6
bedrock_client/src/paths.rs
Normal file
@ -0,0 +1,6 @@
|
||||
pub const CRYPTARCHIA_INFO: &str = "/cryptarchia/info";
|
||||
pub const CRYPTARCHIA_LIB_STREAM: &str = "/cryptarchia/lib-stream";
|
||||
pub const STORAGE_BLOCK: &str = "/storage/block";
|
||||
|
||||
pub const BLOCKS: &str = "/cryptarchia/blocks";
|
||||
pub const BLOCKS_STREAM: &str = "/cryptarchia/blocks/stream";
|
||||
103
bedrock_client/src/structs/header_id.rs
Normal file
103
bedrock_client/src/structs/header_id.rs
Normal file
@ -0,0 +1,103 @@
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Copy, Hash, PartialOrd, Ord)]
|
||||
pub struct HeaderId([u8; 32]);
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error("Invalid header id size: {0}")]
|
||||
InvalidHeaderIdSize(usize),
|
||||
}
|
||||
|
||||
impl From<[u8; 32]> for HeaderId {
|
||||
fn from(id: [u8; 32]) -> Self {
|
||||
Self(id)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<HeaderId> for [u8; 32] {
|
||||
fn from(id: HeaderId) -> Self {
|
||||
id.0
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8]> for HeaderId {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
|
||||
if slice.len() != 32 {
|
||||
return Err(Error::InvalidHeaderIdSize(slice.len()));
|
||||
}
|
||||
let mut id = [0u8; 32];
|
||||
id.copy_from_slice(slice);
|
||||
Ok(Self::from(id))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for HeaderId {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Copy, Hash)]
|
||||
pub struct ContentId([u8; 32]);
|
||||
|
||||
impl From<ContentId> for [u8; 32] {
|
||||
fn from(id: ContentId) -> Self {
|
||||
id.0
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! display_hex_bytes_newtype {
|
||||
($newtype:ty) => {
|
||||
impl core::fmt::Display for $newtype {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
write!(f, "0x")?;
|
||||
for v in self.0 {
|
||||
write!(f, "{:02x}", v)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! serde_bytes_newtype {
|
||||
($newtype:ty, $len:expr) => {
|
||||
impl serde::Serialize for $newtype {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
if serializer.is_human_readable() {
|
||||
const_hex::const_encode::<$len, false>(&self.0)
|
||||
.as_str()
|
||||
.serialize(serializer)
|
||||
} else {
|
||||
self.0.serialize(serializer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> serde::Deserialize<'de> for $newtype {
|
||||
fn deserialize<D>(deserializer: D) -> Result<$newtype, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
if deserializer.is_human_readable() {
|
||||
let s = <String>::deserialize(deserializer)?;
|
||||
const_hex::decode_to_array(s)
|
||||
.map(Self)
|
||||
.map_err(serde::de::Error::custom)
|
||||
} else {
|
||||
<[u8; $len] as serde::Deserialize>::deserialize(deserializer).map(Self)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
display_hex_bytes_newtype!(HeaderId);
|
||||
display_hex_bytes_newtype!(ContentId);
|
||||
|
||||
serde_bytes_newtype!(HeaderId, 32);
|
||||
serde_bytes_newtype!(ContentId, 32);
|
||||
23
bedrock_client/src/structs/info.rs
Normal file
23
bedrock_client/src/structs/info.rs
Normal file
@ -0,0 +1,23 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_with::serde_as;
|
||||
|
||||
use crate::structs::header_id::HeaderId;
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Copy, Hash, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub struct Slot(u64);
|
||||
|
||||
#[derive(Clone, Debug, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum State {
|
||||
Bootstrapping,
|
||||
Online,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct CryptarchiaInfo {
|
||||
pub lib: HeaderId,
|
||||
pub tip: HeaderId,
|
||||
pub slot: Slot,
|
||||
pub height: u64,
|
||||
pub mode: State,
|
||||
}
|
||||
40
bedrock_client/src/structs/mod.rs
Normal file
40
bedrock_client/src/structs/mod.rs
Normal file
@ -0,0 +1,40 @@
|
||||
use ed25519_dalek::Signature;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::structs::{header_id::{ContentId, HeaderId}, info::Slot};
|
||||
|
||||
pub mod header_id;
|
||||
pub mod info;
|
||||
pub mod signature;
|
||||
pub mod tx;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct BlockInfo {
|
||||
pub height: u64,
|
||||
pub header_id: HeaderId,
|
||||
}
|
||||
|
||||
pub const BEDROCK_VERSION: u8 = 1;
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Copy, Serialize, Deserialize)]
|
||||
#[repr(u8)]
|
||||
pub enum Version {
|
||||
Bedrock = BEDROCK_VERSION,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Header {
|
||||
version: Version,
|
||||
parent_block: HeaderId,
|
||||
slot: Slot,
|
||||
block_root: ContentId,
|
||||
// Not sure, if need this.
|
||||
// proof_of_leadership: Groth16LeaderProof,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Block<Tx> {
|
||||
header: Header,
|
||||
signature: Signature,
|
||||
transactions: Vec<Tx>,
|
||||
}
|
||||
53
bedrock_client/src/structs/signature.rs
Normal file
53
bedrock_client/src/structs/signature.rs
Normal file
@ -0,0 +1,53 @@
|
||||
use core::hash::{Hash, Hasher};
|
||||
|
||||
use ed25519_dalek::SIGNATURE_LENGTH;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub const SIGNATURE_SIZE: usize = SIGNATURE_LENGTH;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct Signature(ed25519_dalek::Signature);
|
||||
|
||||
impl Signature {
|
||||
#[must_use]
|
||||
pub fn from_bytes(bytes: &[u8; SIGNATURE_SIZE]) -> Self {
|
||||
Self(ed25519_dalek::Signature::from_bytes(bytes))
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn to_bytes(&self) -> [u8; SIGNATURE_SIZE] {
|
||||
self.0.to_bytes()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn as_inner(&self) -> &ed25519_dalek::Signature {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for Signature {
|
||||
fn hash<H>(&self, state: &mut H)
|
||||
where
|
||||
H: Hasher,
|
||||
{
|
||||
self.0.to_bytes().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ed25519_dalek::Signature> for Signature {
|
||||
fn from(sig: ed25519_dalek::Signature) -> Self {
|
||||
Self(sig)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Signature> for ed25519_dalek::Signature {
|
||||
fn from(sig: Signature) -> Self {
|
||||
sig.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; SIGNATURE_SIZE]> for Signature {
|
||||
fn from(bytes: [u8; SIGNATURE_SIZE]) -> Self {
|
||||
Self::from_bytes(&bytes)
|
||||
}
|
||||
}
|
||||
9
bedrock_client/src/structs/tx.rs
Normal file
9
bedrock_client/src/structs/tx.rs
Normal file
@ -0,0 +1,9 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
|
||||
pub struct SignedMantleTx {
|
||||
pub mantle_tx: MantleTx,
|
||||
pub ops_proofs: Vec<OpProof>,
|
||||
// Not sure, if we need this.
|
||||
// ledger_tx_proof: ZkSignature,
|
||||
}
|
||||
19
indexer/Cargo.toml
Normal file
19
indexer/Cargo.toml
Normal file
@ -0,0 +1,19 @@
|
||||
[package]
|
||||
name = "indexer"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
nssa.workspace = true
|
||||
nssa_core.workspace = true
|
||||
common.workspace = true
|
||||
storage.workspace = true
|
||||
|
||||
base58.workspace = true
|
||||
anyhow.workspace = true
|
||||
serde.workspace = true
|
||||
log.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
|
||||
futures.workspace = true
|
||||
0
indexer/src/client/mod.rs
Normal file
0
indexer/src/client/mod.rs
Normal file
1
indexer/src/lib.rs
Normal file
1
indexer/src/lib.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod client;
|
||||
Loading…
x
Reference in New Issue
Block a user