1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//! ABCI response types used by the `/block_results` RPC endpoint.

use super::{code::Code, data::Data, gas::Gas, info::Info, log::Log, tag::Tag};
use crate::{consensus, serializers, validator};
use serde::{Deserialize, Deserializer, Serialize};
use std::fmt::{self, Display};

/// Responses for ABCI calls which occur during block processing.
///
/// Returned from the `/block_results` RPC endpoint.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Responses {
    /// Deliver TX response.
    // TODO(tarcieri): remove the `alias` attribute when this lands upstream:
    // <https://github.com/tendermint/tendermint/pull/3708/files>
    #[serde(alias = "DeliverTx")]
    #[serde(default, deserialize_with = "deserialize_deliver_tx")]
    pub deliver_tx: Vec<DeliverTx>,

    /// Begin block response.
    // TODO(tarcieri): remove the `alias` attribute when this lands upstream:
    // <https://github.com/tendermint/tendermint/pull/3708/files>
    #[serde(alias = "BeginBlock")]
    pub begin_block: Option<BeginBlock>,

    /// End block response.
    // TODO(tarcieri): remove the `alias` attribute when this lands upstream:
    // <https://github.com/tendermint/tendermint/pull/3708/files>
    #[serde(alias = "EndBlock")]
    pub end_block: Option<EndBlock>,
}

/// Return an empty vec in the event `deliver_tx` is `null`
fn deserialize_deliver_tx<'de, D>(deserializer: D) -> Result<Vec<DeliverTx>, D::Error>
where
    D: Deserializer<'de>,
{
    Ok(Option::deserialize(deserializer)?.unwrap_or_default())
}

/// Deliver TX response.
///
/// This type corresponds to the `ResponseDeliverTx` proto from:
///
/// <https://github.com/tendermint/tendermint/blob/master/abci/types/types.proto>
// TODO(tarcieri): generate this automatically from the proto
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct DeliverTx {
    /// ABCI application response code
    pub code: Code,

    /// ABCI application data
    #[serde(with = "serializers::nullable")]
    pub data: Data,

    /// ABCI log data (nondeterministic)
    pub log: Log,

    /// ABCI info (nondeterministic)
    pub info: Info,

    /// Amount of gas wanted
    #[serde(default)]
    pub gas_wanted: Gas,

    /// Amount of gas used
    #[serde(default)]
    pub gas_used: Gas,

    /// Events
    pub events: Vec<Event>,

    /// Codespace
    pub codespace: Codespace,
}

/// Event
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Event {
    /// Event type
    #[serde(rename = "type")]
    pub type_str: String,

    /// Attributes
    pub attributes: Vec<Tag>,
}

/// Begin block response.
///
/// This type corresponds to the `ResponseBeginBlock` proto from:
///
/// <https://github.com/tendermint/tendermint/blob/develop/abci/types/types.proto>
// TODO(tarcieri): generate this automatically from the proto
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct BeginBlock {
    /// Tags
    #[serde(default)]
    pub tags: Vec<Tag>,
}

/// End block response.
///
/// This type corresponds to the `ResponseEndBlock` proto from:
///
/// <https://github.com/tendermint/tendermint/blob/develop/abci/types/types.proto>
// TODO(tarcieri): generate this automatically from the proto
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct EndBlock {
    /// Validator updates
    #[serde(deserialize_with = "deserialize_validator_updates")]
    pub validator_updates: Vec<validator::Update>,

    /// New consensus params
    pub consensus_param_updates: Option<consensus::Params>,

    /// Tags
    #[serde(default)]
    pub tags: Vec<Tag>,
}

/// Return an empty vec in the event `validator_updates` is `null`
pub fn deserialize_validator_updates<'de, D>(
    deserializer: D,
) -> Result<Vec<validator::Update>, D::Error>
where
    D: Deserializer<'de>,
{
    Ok(Option::deserialize(deserializer)?.unwrap_or_default())
}

/// Codespace
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct Codespace(String);

impl AsRef<str> for Codespace {
    fn as_ref(&self) -> &str {
        self.0.as_ref()
    }
}

impl Display for Codespace {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl Default for Codespace {
    fn default() -> Self {
        Self(String::new())
    }
}