Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ae9c56a

Browse files
committed
feat(chain): add transaction filter for arweave
1 parent 182779f commit ae9c56a

File tree

9 files changed

+169
-47
lines changed

9 files changed

+169
-47
lines changed

Cargo.lock

Lines changed: 10 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

chain/arweave/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ edition = "2021"
77
tonic-build = "0.5.1"
88

99
[dependencies]
10-
base64 = "0.13"
10+
base64-url = "1.4.13"
1111
graph = { path = "../../graph" }
1212
prost = "0.8.0"
1313
prost-types = "0.8.0"

chain/arweave/src/adapter.rs

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
use crate::capabilities::NodeCapabilities;
22
use crate::{data_source::DataSource, Chain};
33
use graph::blockchain as bc;
4-
use graph::firehose::BasicReceiptFilter;
54
use graph::prelude::*;
6-
use prost::Message;
7-
use prost_types::Any;
8-
9-
const BASIC_RECEIPT_FILTER_TYPE_URL: &str =
10-
"type.googleapis.com/sf.arweave.transform.v1.BasicReceiptFilter";
5+
use std::collections::HashSet;
116

127
#[derive(Clone, Debug, Default)]
138
pub struct TriggerFilter {
149
pub(crate) block_filter: ArweaveBlockFilter,
10+
pub(crate) transaction_filter: ArweaveTransactionFilter,
1511
}
1612

1713
impl bc::TriggerFilter<Chain> for TriggerFilter {
1814
fn extend<'a>(&mut self, data_sources: impl Iterator<Item = &'a DataSource> + Clone) {
19-
let TriggerFilter { block_filter } = self;
15+
let TriggerFilter {
16+
block_filter,
17+
transaction_filter,
18+
} = self;
2019

21-
block_filter.extend(ArweaveBlockFilter::from_data_sources(data_sources));
20+
block_filter.extend(ArweaveBlockFilter::from_data_sources(data_sources.clone()));
21+
transaction_filter.extend(ArweaveTransactionFilter::from_data_sources(data_sources));
2222
}
2323

2424
fn node_capabilities(&self) -> NodeCapabilities {
@@ -32,23 +32,41 @@ impl bc::TriggerFilter<Chain> for TriggerFilter {
3232
}
3333

3434
fn to_firehose_filter(self) -> Vec<prost_types::Any> {
35-
let TriggerFilter {
36-
block_filter: block,
37-
} = self;
35+
vec![]
36+
}
37+
}
3838

39-
if block.trigger_every_block {
40-
return vec![];
41-
}
39+
/// ArweaveBlockFilter will match every block regardless of source being set.
40+
/// see docs: https://thegraph.com/docs/en/supported-networks/arweave/
41+
#[derive(Clone, Debug, Default)]
42+
pub(crate) struct ArweaveTransactionFilter {
43+
owners: HashSet<Vec<u8>>,
44+
}
4245

43-
// # NOTE
44-
//
45-
// Arweave don't have receipts
46-
let filter = BasicReceiptFilter { accounts: vec![] };
46+
impl ArweaveTransactionFilter {
47+
pub fn matches(&self, owner: &[u8]) -> bool {
48+
self.owners.contains(owner)
49+
}
50+
51+
pub fn from_data_sources<'a>(iter: impl IntoIterator<Item = &'a DataSource>) -> Self {
52+
let owners: Vec<Vec<u8>> = iter
53+
.into_iter()
54+
.filter(|data_source| {
55+
data_source.source.owner.is_some()
56+
&& !data_source.mapping.transaction_handlers.is_empty()
57+
})
58+
.map(|ds| {
59+
base64_url::decode(&ds.source.owner.clone().unwrap_or_default()).unwrap_or_default()
60+
})
61+
.collect();
62+
63+
Self {
64+
owners: HashSet::from_iter(owners),
65+
}
66+
}
4767

48-
vec![Any {
49-
type_url: BASIC_RECEIPT_FILTER_TYPE_URL.into(),
50-
value: filter.encode_to_vec(),
51-
}]
68+
pub fn extend(&mut self, other: ArweaveTransactionFilter) {
69+
self.owners.extend(other.owners);
5270
}
5371
}
5472

chain/arweave/src/chain.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use crate::adapter::TriggerFilter;
2424
use crate::capabilities::NodeCapabilities;
2525
use crate::data_source::{DataSourceTemplate, UnresolvedDataSourceTemplate};
2626
use crate::runtime::RuntimeAdapter;
27-
use crate::trigger::ArweaveTrigger;
27+
use crate::trigger::{self, ArweaveTrigger};
2828
use crate::{
2929
codec,
3030
data_source::{DataSource, UnresolvedDataSource},
@@ -198,9 +198,26 @@ impl TriggersAdapterTrait<Chain> for TriggersAdapter {
198198
// TODO: Find the best place to introduce an `Arc` and avoid this clone.
199199
let shared_block = Arc::new(block.clone());
200200

201-
let TriggerFilter { block_filter } = filter;
202-
203-
let mut trigger_data: Vec<ArweaveTrigger> = Vec::new();
201+
let TriggerFilter {
202+
block_filter,
203+
transaction_filter,
204+
} = filter;
205+
206+
let txs = block
207+
.clone()
208+
.txs
209+
.into_iter()
210+
.filter(|tx| transaction_filter.matches(&tx.owner))
211+
.map(|tx| trigger::TransactionWithBlockPtr {
212+
tx: Arc::new(tx.clone()),
213+
block: shared_block.clone(),
214+
})
215+
.collect::<Vec<_>>();
216+
217+
let mut trigger_data: Vec<_> = txs
218+
.into_iter()
219+
.map(|tx| ArweaveTrigger::Transaction(Arc::new(tx)))
220+
.collect();
204221

205222
if block_filter.trigger_every_block {
206223
trigger_data.push(ArweaveTrigger::Block(shared_block.cheap_clone()));

chain/arweave/src/data_source.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,11 @@ pub struct DataSource {
3232
}
3333

3434
impl blockchain::DataSource<Chain> for DataSource {
35+
// FIXME
36+
//
37+
// need to decode the base64url encoding?
3538
fn address(&self) -> Option<&[u8]> {
36-
self.source.account.as_ref().map(String::as_bytes)
39+
self.source.owner.as_ref().map(String::as_bytes)
3740
}
3841

3942
fn start_block(&self) -> BlockNumber {
@@ -56,6 +59,11 @@ impl blockchain::DataSource<Chain> for DataSource {
5659
Some(handler) => &handler.handler,
5760
None => return Ok(None),
5861
},
62+
// A transaction trigger matches if a transaction handler is present.
63+
ArweaveTrigger::Transaction(_) => match self.handler_for_transaction() {
64+
Some(handler) => &handler.handler,
65+
None => return Ok(None),
66+
},
5967
};
6068

6169
Ok(Some(TriggerWithHandler::new(
@@ -186,6 +194,10 @@ impl DataSource {
186194
fn handler_for_block(&self) -> Option<&MappingBlockHandler> {
187195
self.mapping.block_handlers.first()
188196
}
197+
198+
fn handler_for_transaction(&self) -> Option<&TransactionHandler> {
199+
self.mapping.transaction_handlers.first()
200+
}
189201
}
190202

191203
#[derive(Clone, Debug, Eq, PartialEq, Deserialize)]
@@ -214,7 +226,7 @@ impl blockchain::UnresolvedDataSource<Chain> for UnresolvedDataSource {
214226
context,
215227
} = self;
216228

217-
info!(logger, "Resolve data source"; "name" => &name, "source_address" => format_args!("{:?}", source.account), "source_start_block" => source.start_block);
229+
info!(logger, "Resolve data source"; "name" => &name, "source_address" => format_args!("{:?}", base64_url::encode(&source.owner.clone().unwrap_or_default())), "source_start_block" => source.start_block);
218230

219231
let mapping = mapping.resolve(resolver, logger).await?;
220232

@@ -346,13 +358,13 @@ pub struct MappingBlockHandler {
346358

347359
#[derive(Clone, Debug, Hash, Eq, PartialEq, Deserialize)]
348360
pub struct TransactionHandler {
349-
handler: String,
361+
pub handler: String,
350362
}
351363

352364
#[derive(Clone, Debug, Hash, Eq, PartialEq, Deserialize)]
353365
pub(crate) struct Source {
354-
// A data source that does not have an account can only have block handlers.
355-
pub(crate) account: Option<String>,
366+
// A data source that does not have an owner can only have block handlers.
367+
pub(crate) owner: Option<String>,
356368
#[serde(rename = "startBlock", default)]
357369
pub(crate) start_block: BlockNumber,
358370
}

chain/arweave/src/runtime/abi.rs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use crate::codec;
2+
use crate::trigger::TransactionWithBlockPtr;
23
use graph::runtime::gas::GasCounter;
34
use graph::runtime::{asc_new, AscHeap, AscPtr, DeterministicHostError, ToAscObj};
4-
use graph_runtime_wasm::asc_abi::class::Array;
5+
use graph_runtime_wasm::asc_abi::class::{Array, Uint8Array};
56

67
pub(crate) use super::generated::*;
78

@@ -18,16 +19,16 @@ impl ToAscObj<AscTag> for codec::Tag {
1819
}
1920
}
2021

21-
impl ToAscObj<AscTransactionArray> for Vec<codec::Transaction> {
22+
impl ToAscObj<AscTransactionArray> for Vec<Vec<u8>> {
2223
fn to_asc_obj<H: AscHeap + ?Sized>(
2324
&self,
2425
heap: &mut H,
2526
gas: &GasCounter,
2627
) -> Result<AscTransactionArray, DeterministicHostError> {
2728
let content = self
28-
.iter()
29-
.map(|x| asc_new(heap, x, gas))
30-
.collect::<Result<Vec<_>, _>>()?;
29+
.into_iter()
30+
.map(|x| asc_new(heap, x.as_slice(), gas))
31+
.collect::<Result<Vec<AscPtr<Uint8Array>>, _>>()?;
3132
Ok(AscTransactionArray(Array::new(&*content, heap, gas)?))
3233
}
3334
}
@@ -109,7 +110,6 @@ impl ToAscObj<AscBlock> for codec::Block {
109110
gas: &GasCounter,
110111
) -> Result<AscBlock, DeterministicHostError> {
111112
Ok(AscBlock {
112-
// ver: self.ver,
113113
indep_hash: asc_new(heap, self.indep_hash.as_slice(), gas)?,
114114
nonce: asc_new(heap, self.nonce.as_slice(), gas)?,
115115
previous_block: asc_new(heap, self.previous_block.as_slice(), gas)?,
@@ -123,7 +123,15 @@ impl ToAscObj<AscBlock> for codec::Block {
123123
height: self.height,
124124
hash: asc_new(heap, self.hash.as_slice(), gas)?,
125125
tx_root: asc_new(heap, self.tx_root.as_slice(), gas)?,
126-
txs: asc_new(heap, &self.txs, gas)?,
126+
txs: asc_new(
127+
heap,
128+
&self
129+
.txs
130+
.iter()
131+
.map(|tx| tx.id.clone().into())
132+
.collect::<Vec<Vec<u8>>>(),
133+
gas,
134+
)?,
127135
wallet_list: asc_new(heap, self.wallet_list.as_slice(), gas)?,
128136
reward_addr: asc_new(heap, self.reward_addr.as_slice(), gas)?,
129137
tags: asc_new(heap, &self.tags, gas)?,
@@ -168,3 +176,16 @@ impl ToAscObj<AscBlock> for codec::Block {
168176
})
169177
}
170178
}
179+
180+
impl ToAscObj<AscTransactionWithBlockPtr> for TransactionWithBlockPtr {
181+
fn to_asc_obj<H: AscHeap + ?Sized>(
182+
&self,
183+
heap: &mut H,
184+
gas: &GasCounter,
185+
) -> Result<AscTransactionWithBlockPtr, DeterministicHostError> {
186+
Ok(AscTransactionWithBlockPtr {
187+
tx: asc_new(heap, &self.tx.as_ref(), gas)?,
188+
block: asc_new(heap, self.block.as_ref(), gas)?,
189+
})
190+
}
191+
}

chain/arweave/src/runtime/generated.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ impl AscIndexId for AscTag {
7878
}
7979

8080
#[repr(C)]
81-
pub struct AscTransactionArray(pub(crate) Array<AscPtr<AscTransaction>>);
81+
pub struct AscTransactionArray(pub(crate) Array<AscPtr<Uint8Array>>);
8282

8383
impl AscType for AscTransactionArray {
8484
fn to_asc_bytes(&self) -> Result<Vec<u8>, DeterministicHostError> {
@@ -116,3 +116,14 @@ impl AscType for AscTagArray {
116116
impl AscIndexId for AscTagArray {
117117
const INDEX_ASC_TYPE_ID: IndexForAscTypeId = IndexForAscTypeId::ArweaveTagArray;
118118
}
119+
120+
#[repr(C)]
121+
#[derive(AscType)]
122+
pub struct AscTransactionWithBlockPtr {
123+
pub tx: AscPtr<AscTransaction>,
124+
pub block: AscPtr<AscBlock>,
125+
}
126+
127+
impl AscIndexId for AscTransactionWithBlockPtr {
128+
const INDEX_ASC_TYPE_ID: IndexForAscTypeId = IndexForAscTypeId::ArweaveTransactionWithBlockPtr;
129+
}

0 commit comments

Comments
 (0)