#[cfg(feature = "echo-app")]
pub mod echo;
#[cfg(feature = "kvstore-app")]
pub mod kvstore;
use tendermint_proto::v0_38::abci::{
request::Value, response, response_process_proposal, response_verify_vote_extension, Request,
RequestApplySnapshotChunk, RequestCheckTx, RequestEcho, RequestExtendVote,
RequestFinalizeBlock, RequestInfo, RequestInitChain, RequestLoadSnapshotChunk,
RequestOfferSnapshot, RequestPrepareProposal, RequestProcessProposal, RequestQuery,
RequestVerifyVoteExtension, Response, ResponseApplySnapshotChunk, ResponseCheckTx,
ResponseCommit, ResponseEcho, ResponseExtendVote, ResponseFinalizeBlock, ResponseFlush,
ResponseInfo, ResponseInitChain, ResponseListSnapshots, ResponseLoadSnapshotChunk,
ResponseOfferSnapshot, ResponsePrepareProposal, ResponseProcessProposal, ResponseQuery,
ResponseVerifyVoteExtension,
};
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 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,
}
}
fn extend_vote(&self, _request: RequestExtendVote) -> ResponseExtendVote {
Default::default()
}
fn verify_vote_extension(
&self,
_request: RequestVerifyVoteExtension,
) -> ResponseVerifyVoteExtension {
ResponseVerifyVoteExtension {
status: response_verify_vote_extension::VerifyStatus::Accept as i32,
}
}
fn finalize_block(&self, _request: RequestFinalizeBlock) -> ResponseFinalizeBlock {
Default::default()
}
}
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::CheckTx(req) => response::Value::CheckTx(self.check_tx(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))
},
Value::ExtendVote(req) => response::Value::ExtendVote(self.extend_vote(req)),
Value::VerifyVoteExtension(req) => {
response::Value::VerifyVoteExtension(self.verify_vote_extension(req))
},
Value::FinalizeBlock(req) => {
response::Value::FinalizeBlock(self.finalize_block(req))
},
}),
}
}
}