#[cfg(feature = "echo-app")]
pub mod echo;
#[cfg(feature = "kvstore-app")]
pub mod kvstore;
use tendermint_proto::v0_37::abci::{
request::Value, response, response_process_proposal, Request, RequestApplySnapshotChunk,
RequestBeginBlock, RequestCheckTx, RequestDeliverTx, RequestEcho, RequestEndBlock, RequestInfo,
RequestInitChain, RequestLoadSnapshotChunk, RequestOfferSnapshot, RequestPrepareProposal,
RequestProcessProposal, RequestQuery, Response, ResponseApplySnapshotChunk, ResponseBeginBlock,
ResponseCheckTx, ResponseCommit, ResponseDeliverTx, ResponseEcho, ResponseEndBlock,
ResponseFlush, ResponseInfo, ResponseInitChain, ResponseListSnapshots,
ResponseLoadSnapshotChunk, ResponseOfferSnapshot, ResponsePrepareProposal,
ResponseProcessProposal, ResponseQuery,
};
pub trait Application: Send + Clone + 'static {
fn echo(&self, request: RequestEcho) -> ResponseEcho {
ResponseEcho {
message: request.message,
}
}
fn info(&self, _request: RequestInfo) -> ResponseInfo {
Default::default()
}
fn init_chain(&self, _request: RequestInitChain) -> ResponseInitChain {
Default::default()
}
fn query(&self, _request: RequestQuery) -> ResponseQuery {
Default::default()
}
fn check_tx(&self, _request: RequestCheckTx) -> ResponseCheckTx {
Default::default()
}
fn begin_block(&self, _request: RequestBeginBlock) -> ResponseBeginBlock {
Default::default()
}
fn deliver_tx(&self, _request: RequestDeliverTx) -> ResponseDeliverTx {
Default::default()
}
fn end_block(&self, _request: RequestEndBlock) -> ResponseEndBlock {
Default::default()
}
fn flush(&self) -> ResponseFlush {
ResponseFlush {}
}
fn commit(&self) -> ResponseCommit {
Default::default()
}
fn list_snapshots(&self) -> ResponseListSnapshots {
Default::default()
}
fn offer_snapshot(&self, _request: RequestOfferSnapshot) -> ResponseOfferSnapshot {
Default::default()
}
fn load_snapshot_chunk(&self, _request: RequestLoadSnapshotChunk) -> ResponseLoadSnapshotChunk {
Default::default()
}
fn apply_snapshot_chunk(
&self,
_request: RequestApplySnapshotChunk,
) -> ResponseApplySnapshotChunk {
Default::default()
}
fn prepare_proposal(&self, request: RequestPrepareProposal) -> ResponsePrepareProposal {
let RequestPrepareProposal {
mut txs,
max_tx_bytes,
..
} = request;
let max_tx_bytes: usize = max_tx_bytes.try_into().unwrap_or(0);
let mut total_tx_bytes: usize = txs
.iter()
.map(|tx| tx.len())
.fold(0, |acc, len| acc.saturating_add(len));
while total_tx_bytes > max_tx_bytes {
if let Some(tx) = txs.pop() {
total_tx_bytes = total_tx_bytes.saturating_sub(tx.len());
} else {
break;
}
}
ResponsePrepareProposal { txs }
}
fn process_proposal(&self, _request: RequestProcessProposal) -> ResponseProcessProposal {
ResponseProcessProposal {
status: response_process_proposal::ProposalStatus::Accept as i32,
}
}
}
pub trait RequestDispatcher {
fn handle(&self, request: Request) -> Response;
}
impl<A: Application> RequestDispatcher for A {
fn handle(&self, request: Request) -> Response {
tracing::debug!("Incoming request: {:?}", request);
Response {
value: Some(match request.value.unwrap() {
Value::Echo(req) => response::Value::Echo(self.echo(req)),
Value::Flush(_) => response::Value::Flush(self.flush()),
Value::Info(req) => response::Value::Info(self.info(req)),
Value::InitChain(req) => response::Value::InitChain(self.init_chain(req)),
Value::Query(req) => response::Value::Query(self.query(req)),
Value::BeginBlock(req) => response::Value::BeginBlock(self.begin_block(req)),
Value::CheckTx(req) => response::Value::CheckTx(self.check_tx(req)),
Value::DeliverTx(req) => response::Value::DeliverTx(self.deliver_tx(req)),
Value::EndBlock(req) => response::Value::EndBlock(self.end_block(req)),
Value::Commit(_) => response::Value::Commit(self.commit()),
Value::ListSnapshots(_) => response::Value::ListSnapshots(self.list_snapshots()),
Value::OfferSnapshot(req) => {
response::Value::OfferSnapshot(self.offer_snapshot(req))
},
Value::LoadSnapshotChunk(req) => {
response::Value::LoadSnapshotChunk(self.load_snapshot_chunk(req))
},
Value::ApplySnapshotChunk(req) => {
response::Value::ApplySnapshotChunk(self.apply_snapshot_chunk(req))
},
Value::PrepareProposal(req) => {
response::Value::PrepareProposal(self.prepare_proposal(req))
},
Value::ProcessProposal(req) => {
response::Value::ProcessProposal(self.process_proposal(req))
},
}),
}
}
}