Skip to content

Commit 5c673ef

Browse files
committed
Implement datum bytes fields chunks
To avoid the limitation of 128 bytes for the bytes fields in the datum, we need to chunk these fields. This is a temporary fix that will be removed when Cardano 1.36 is released.
1 parent fa2cf90 commit 5c673ef

File tree

1 file changed

+44
-18
lines changed
  • mithril-common/src/chain_observer

1 file changed

+44
-18
lines changed

mithril-common/src/chain_observer/model.rs

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,11 @@ pub enum TxDatumError {
2424
pub struct TxDatum(pub String);
2525

2626
impl TxDatum {
27-
/// Retrieves the nth field of the datum with given type
28-
pub fn get_nth_field_by_type(
27+
/// Retrieves the fields of the datum with given type
28+
pub fn get_fields_by_type(
2929
&self,
3030
type_name: &TxDatumFieldTypeName,
31-
index: usize,
32-
) -> Result<Value, Box<dyn StdError>> {
31+
) -> Result<Vec<Value>, Box<dyn StdError>> {
3332
let tx_datum_raw = &self.0;
3433
// 1- Parse the Utxo raw data to a hashmap
3534
let v: HashMap<String, Value> = serde_json::from_str(tx_datum_raw).map_err(|e| {
@@ -48,22 +47,28 @@ impl TxDatum {
4847
)
4948
})?;
5049
// 3- Filter the vec (keep the ones that match the given type), and retrieve the nth entry of this filtered vec
51-
let field_value = fields
50+
Ok(fields
5251
.iter()
5352
.filter(|&field| field.get(type_name.to_string()).is_some())
54-
.nth(index)
53+
.map(|field| field.get(type_name.to_string()).unwrap().to_owned())
54+
.collect::<_>())
55+
}
56+
57+
/// Retrieves the nth field of the datum with given type
58+
pub fn get_nth_field_by_type(
59+
&self,
60+
type_name: &TxDatumFieldTypeName,
61+
index: usize,
62+
) -> Result<Value, Box<dyn StdError>> {
63+
Ok(self
64+
.get_fields_by_type(type_name)?
65+
.get(index)
5566
.ok_or_else(|| {
5667
TxDatumError::InvalidContent(
57-
format!(
58-
"Error: missing field at index {index}, tx datum was = '{tx_datum_raw}'"
59-
)
60-
.into(),
68+
format!("Error: missing field at index {index}").into(),
6169
)
6270
})?
63-
.get(type_name.to_string())
64-
.unwrap();
65-
66-
Ok(field_value.to_owned())
71+
.to_owned())
6772
}
6873
}
6974

@@ -101,9 +106,29 @@ impl TxDatumBuilder {
101106

102107
/// Add a field to the builder
103108
pub fn add_field(&mut self, field_value: TxDatumFieldValue) -> &mut TxDatumBuilder {
104-
let mut field = HashMap::new();
105-
field.insert(TxDatumFieldTypeName::from(&field_value), field_value);
106-
self.fields.push(field);
109+
match &field_value {
110+
TxDatumFieldValue::Bytes(datum_str) => {
111+
// TODO: Remove this chunking of the bytes fields once the cardano-cli 1.36.0+ is released
112+
// The bytes fields are currently limited to 128 bytes and need to be chunked in multiple fields
113+
let field_type = TxDatumFieldTypeName::from(&field_value);
114+
let field_value_chunks = datum_str.as_bytes().chunks(128);
115+
for field_value_chunk in field_value_chunks {
116+
let mut field = HashMap::new();
117+
field.insert(
118+
field_type,
119+
TxDatumFieldValue::Bytes(
120+
std::str::from_utf8(field_value_chunk).unwrap().to_string(),
121+
),
122+
);
123+
self.fields.push(field);
124+
}
125+
}
126+
_ => {
127+
let mut field = HashMap::new();
128+
field.insert(TxDatumFieldTypeName::from(&field_value), field_value);
129+
self.fields.push(field);
130+
}
131+
}
107132

108133
self
109134
}
@@ -135,6 +160,7 @@ mod test {
135160
.add_field(TxDatumFieldValue::Bytes("bytes1".to_string()))
136161
.add_field(TxDatumFieldValue::Bytes("bytes2".to_string()))
137162
.add_field(TxDatumFieldValue::Int(2))
163+
.add_field(TxDatumFieldValue::Bytes("012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789".to_string()))
138164
.build()
139165
.expect("tx_datum build should not fail");
140166
tx_datum
@@ -143,7 +169,7 @@ mod test {
143169
#[test]
144170
fn test_build_tx_datum() {
145171
let tx_datum = dummy_tx_datum();
146-
let tx_datum_expected = TxDatum(r#"{"constructor":0,"fields":[{"bytes":"bytes0"},{"int":0},{"int":1},{"bytes":"bytes1"},{"bytes":"bytes2"},{"int":2}]}"#.to_string());
172+
let tx_datum_expected = TxDatum(r#"{"constructor":0,"fields":[{"bytes":"bytes0"},{"int":0},{"int":1},{"bytes":"bytes1"},{"bytes":"bytes2"},{"int":2},{"bytes":"01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567"},{"bytes":"8901234567890123456789"}]}"#.to_string());
147173
assert_eq!(tx_datum_expected, tx_datum);
148174
}
149175

0 commit comments

Comments
 (0)