From ebec46412c5bc86832f4fb8a6569008d1e2a5a95 Mon Sep 17 00:00:00 2001 From: Fabien Penso Date: Fri, 29 Mar 2024 19:05:21 +0100 Subject: [PATCH 01/16] tendermint: Add `Vec` for `EventAttribute` for 0.34 (#1400) 0.34 doesn't enforce UTF8 for event attribute values. Adding a Vec for those, and keeping String for later versions. --- .../1405-change-event-attribute-value.md | 4 + rpc/src/dialect/v0_34.rs | 14 +- rpc/tests/kvstore_fixtures/v0_34.rs | 106 +++++---- rpc/tests/kvstore_fixtures/v0_37.rs | 106 +++++---- rpc/tests/kvstore_fixtures/v0_38.rs | 90 ++++--- tendermint/src/abci.rs | 1 + tendermint/src/abci/event.rs | 225 ++++++++++++++---- 7 files changed, 366 insertions(+), 180 deletions(-) create mode 100644 .changelog/unreleased/breaking-changes/1405-change-event-attribute-value.md diff --git a/.changelog/unreleased/breaking-changes/1405-change-event-attribute-value.md b/.changelog/unreleased/breaking-changes/1405-change-event-attribute-value.md new file mode 100644 index 000000000..9ccdc2555 --- /dev/null +++ b/.changelog/unreleased/breaking-changes/1405-change-event-attribute-value.md @@ -0,0 +1,4 @@ +- `[tendermint]` Change `EventAttribute` `value` from `String` to `Vec` for + TM34. `key`, `value` and `index` now have to be called through `key()`, + `value_str()` and `index()` to support both `Vec` and `String`. + ([\#1400](https://github.com/informalsystems/tendermint-rs/issues/1400)). diff --git a/rpc/src/dialect/v0_34.rs b/rpc/src/dialect/v0_34.rs index 2102b71fa..0c0f8b621 100644 --- a/rpc/src/dialect/v0_34.rs +++ b/rpc/src/dialect/v0_34.rs @@ -50,9 +50,9 @@ pub struct EventAttribute { /// The event value. #[serde( serialize_with = "base64string::serialize", - deserialize_with = "base64string::deserialize_to_string" + deserialize_with = "base64string::deserialize" )] - pub value: String, + pub value: Vec, /// Whether Tendermint's indexer should index this event. /// /// **This field is nondeterministic**. @@ -61,20 +61,20 @@ pub struct EventAttribute { impl From for abci::EventAttribute { fn from(msg: EventAttribute) -> Self { - Self { + Self::V034(abci::v0_34::EventAttribute { key: msg.key, value: msg.value, index: msg.index, - } + }) } } impl From for EventAttribute { fn from(msg: abci::EventAttribute) -> Self { Self { - key: msg.key, - value: msg.value, - index: msg.index, + key: msg.key().clone(), + value: msg.value_as_bytes().to_vec(), + index: msg.index(), } } } diff --git a/rpc/tests/kvstore_fixtures/v0_34.rs b/rpc/tests/kvstore_fixtures/v0_34.rs index 1b845b544..c307bf790 100644 --- a/rpc/tests/kvstore_fixtures/v0_34.rs +++ b/rpc/tests/kvstore_fixtures/v0_34.rs @@ -509,21 +509,35 @@ fn incoming_fixtures() { assert!(result.tx_result.data.is_empty()); assert_eq!(result.tx_result.events.len(), 1); assert_eq!(result.tx_result.events[0].attributes.len(), 4); - assert_eq!(result.tx_result.events[0].attributes[0].key, "creator"); + assert_eq!(result.tx_result.events[0].attributes[0].key(), "creator"); assert_eq!( - result.tx_result.events[0].attributes[0].value, + result.tx_result.events[0].attributes[0] + .value_str() + .unwrap(), "Cosmoshi Netowoko" ); - assert_eq!(result.tx_result.events[0].attributes[1].key, "key"); - assert_eq!(result.tx_result.events[0].attributes[1].value, "commit-key"); - assert_eq!(result.tx_result.events[0].attributes[2].key, "index_key"); + assert_eq!(result.tx_result.events[0].attributes[1].key(), "key"); assert_eq!( - result.tx_result.events[0].attributes[2].value, + result.tx_result.events[0].attributes[1] + .value_str() + .unwrap(), + "commit-key" + ); + assert_eq!(result.tx_result.events[0].attributes[2].key(), "index_key"); + assert_eq!( + result.tx_result.events[0].attributes[2] + .value_str() + .unwrap(), "index is working" ); - assert_eq!(result.tx_result.events[0].attributes[3].key, "noindex_key"); assert_eq!( - result.tx_result.events[0].attributes[3].value, + result.tx_result.events[0].attributes[3].key(), + "noindex_key" + ); + assert_eq!( + result.tx_result.events[0].attributes[3] + .value_str() + .unwrap(), "index is working" ); assert_eq!(result.tx_result.events[0].kind, "app"); @@ -908,23 +922,23 @@ fn incoming_fixtures() { assert_eq!(rbb.events.len(), 2); assert_eq!(rbb.events[0].kind, "transfer"); assert_eq!(rbb.events[0].attributes.len(), 2); - assert_eq!(rbb.events[0].attributes[0].key, "recipient"); + assert_eq!(rbb.events[0].attributes[0].key(), "recipient"); assert_eq!( - rbb.events[0].attributes[0].value, + rbb.events[0].attributes[0].value_str().unwrap(), "cosmos17xpfvakm2amg962yls6f84z3kell8c5lserqta" ); - assert!(rbb.events[0].attributes[0].index); - assert_eq!(rbb.events[0].attributes[1].key, "sender"); + assert!(rbb.events[0].attributes[0].index()); + assert_eq!(rbb.events[0].attributes[1].key(), "sender"); assert_eq!( - rbb.events[0].attributes[1].value, + rbb.events[0].attributes[1].value_str().unwrap(), "cosmos1m3h30wlvsf8llruxtpukdvsy0km2kum8g38c8q" ); - assert!(!rbb.events[0].attributes[1].index); + assert!(!rbb.events[0].attributes[1].index()); assert_eq!(rbb.events[1].kind, "message"); assert_eq!(rbb.events[1].attributes.len(), 1); - assert_eq!(rbb.events[1].attributes[0].key, "sender"); + assert_eq!(rbb.events[1].attributes[0].key(), "sender"); assert_eq!( - rbb.events[1].attributes[0].value, + rbb.events[1].attributes[0].value_str().unwrap(), "cosmos1m3h30wlvsf8llruxtpukdvsy0km2kum8g38c8q" ); let reb = result_end_block.unwrap(); @@ -1115,18 +1129,18 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 1); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key.as_str() { + match attr.key().as_str() { "creator" => { - assert_eq!(attr.value, "Cosmoshi Netowoko") + assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, - "key" => assert_eq!(attr.value, "tx0"), + "key" => assert_eq!(attr.value_str().unwrap(), "tx0"), "index_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, "noindex_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key), + _ => panic!("unknown attribute found {}", attr.key()), } } assert_eq!(tx_result.tx, base64::decode("dHgwPXZhbHVl").unwrap()); @@ -1147,18 +1161,18 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 1); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key.as_str() { + match attr.key().as_str() { "creator" => { - assert_eq!(attr.value, "Cosmoshi Netowoko") + assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, - "key" => assert_eq!(attr.value, "tx1"), + "key" => assert_eq!(attr.value_str().unwrap(), "tx1"), "index_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, "noindex_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key), + _ => panic!("unknown attribute found {}", attr.key()), } } assert_eq!(tx_result.tx, base64::decode("dHgxPXZhbHVl").unwrap()); @@ -1180,18 +1194,18 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 1); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key.as_str() { + match attr.key().as_str() { "creator" => { - assert_eq!(attr.value, "Cosmoshi Netowoko") + assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, - "key" => assert_eq!(attr.value, "tx2"), + "key" => assert_eq!(attr.value_str().unwrap(), "tx2"), "index_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, "noindex_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key), + _ => panic!("unknown attribute found {}", attr.key()), } } assert_eq!(tx_result.tx, base64::decode("dHgyPXZhbHVl").unwrap()); @@ -1212,18 +1226,18 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 1); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key.as_str() { + match attr.key().as_str() { "creator" => { - assert_eq!(attr.value, "Cosmoshi Netowoko") + assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, - "key" => assert_eq!(attr.value, "tx3"), + "key" => assert_eq!(attr.value_str().unwrap(), "tx3"), "index_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, "noindex_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key), + _ => panic!("unknown attribute found {}", attr.key()), } } assert_eq!(tx_result.tx, base64::decode("dHgzPXZhbHVl").unwrap()); @@ -1244,18 +1258,18 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 1); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key.as_str() { + match attr.key().as_str() { "creator" => { - assert_eq!(attr.value, "Cosmoshi Netowoko") + assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, - "key" => assert_eq!(attr.value, "tx4"), + "key" => assert_eq!(attr.value_str().unwrap(), "tx4"), "index_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, "noindex_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key), + _ => panic!("unknown attribute found {}", attr.key()), } } assert_eq!(tx_result.tx, base64::decode("dHg0PXZhbHVl").unwrap()); diff --git a/rpc/tests/kvstore_fixtures/v0_37.rs b/rpc/tests/kvstore_fixtures/v0_37.rs index b3fd3eac8..3bdf8b43d 100644 --- a/rpc/tests/kvstore_fixtures/v0_37.rs +++ b/rpc/tests/kvstore_fixtures/v0_37.rs @@ -503,21 +503,35 @@ fn incoming_fixtures() { assert!(result.tx_result.data.is_empty()); assert_eq!(result.tx_result.events.len(), 2); assert_eq!(result.tx_result.events[0].attributes.len(), 4); - assert_eq!(result.tx_result.events[0].attributes[0].key, "creator"); + assert_eq!(result.tx_result.events[0].attributes[0].key(), "creator"); assert_eq!( - result.tx_result.events[0].attributes[0].value, + result.tx_result.events[0].attributes[0] + .value_str() + .unwrap(), "Cosmoshi Netowoko" ); - assert_eq!(result.tx_result.events[0].attributes[1].key, "key"); - assert_eq!(result.tx_result.events[0].attributes[1].value, "commit-key"); - assert_eq!(result.tx_result.events[0].attributes[2].key, "index_key"); + assert_eq!(result.tx_result.events[0].attributes[1].key(), "key"); assert_eq!( - result.tx_result.events[0].attributes[2].value, + result.tx_result.events[0].attributes[1] + .value_str() + .unwrap(), + "commit-key" + ); + assert_eq!(result.tx_result.events[0].attributes[2].key(), "index_key"); + assert_eq!( + result.tx_result.events[0].attributes[2] + .value_str() + .unwrap(), "index is working" ); - assert_eq!(result.tx_result.events[0].attributes[3].key, "noindex_key"); assert_eq!( - result.tx_result.events[0].attributes[3].value, + result.tx_result.events[0].attributes[3].key(), + "noindex_key" + ); + assert_eq!( + result.tx_result.events[0].attributes[3] + .value_str() + .unwrap(), "index is working" ); assert_eq!(result.tx_result.events[0].kind, "app"); @@ -902,23 +916,23 @@ fn incoming_fixtures() { assert_eq!(rbb.events.len(), 2); assert_eq!(rbb.events[0].kind, "transfer"); assert_eq!(rbb.events[0].attributes.len(), 2); - assert_eq!(rbb.events[0].attributes[0].key, "recipient"); + assert_eq!(rbb.events[0].attributes[0].key(), "recipient"); assert_eq!( - rbb.events[0].attributes[0].value, + rbb.events[0].attributes[0].value_str().unwrap(), "cosmos17xpfvakm2amg962yls6f84z3kell8c5lserqta" ); - assert!(rbb.events[0].attributes[0].index); - assert_eq!(rbb.events[0].attributes[1].key, "sender"); + assert!(rbb.events[0].attributes[0].index()); + assert_eq!(rbb.events[0].attributes[1].key(), "sender"); assert_eq!( - rbb.events[0].attributes[1].value, + rbb.events[0].attributes[1].value_str().unwrap(), "cosmos1m3h30wlvsf8llruxtpukdvsy0km2kum8g38c8q" ); - assert!(!rbb.events[0].attributes[1].index); + assert!(!rbb.events[0].attributes[1].index()); assert_eq!(rbb.events[1].kind, "message"); assert_eq!(rbb.events[1].attributes.len(), 1); - assert_eq!(rbb.events[1].attributes[0].key, "sender"); + assert_eq!(rbb.events[1].attributes[0].key(), "sender"); assert_eq!( - rbb.events[1].attributes[0].value, + rbb.events[1].attributes[0].value_str().unwrap(), "cosmos1m3h30wlvsf8llruxtpukdvsy0km2kum8g38c8q" ); let reb = result_end_block.unwrap(); @@ -1109,18 +1123,18 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 2); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key.as_str() { + match attr.key().as_str() { "creator" => { - assert_eq!(attr.value, "Cosmoshi Netowoko") + assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, - "key" => assert_eq!(attr.value, "tx0"), + "key" => assert_eq!(attr.value_str().unwrap(), "tx0"), "index_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, "noindex_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key), + _ => panic!("unknown attribute found {}", attr.key()), } } assert_eq!(tx_result.tx, base64::decode("dHgwPXZhbHVl").unwrap()); @@ -1141,18 +1155,18 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 2); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key.as_str() { + match attr.key().as_str() { "creator" => { - assert_eq!(attr.value, "Cosmoshi Netowoko") + assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, - "key" => assert_eq!(attr.value, "tx1"), + "key" => assert_eq!(attr.value_str().unwrap(), "tx1"), "index_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, "noindex_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key), + _ => panic!("unknown attribute found {}", attr.key()), } } assert_eq!(tx_result.tx, base64::decode("dHgxPXZhbHVl").unwrap()); @@ -1174,18 +1188,18 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 2); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key.as_str() { + match attr.key().as_str() { "creator" => { - assert_eq!(attr.value, "Cosmoshi Netowoko") + assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, - "key" => assert_eq!(attr.value, "tx2"), + "key" => assert_eq!(attr.value_str().unwrap(), "tx2"), "index_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, "noindex_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key), + _ => panic!("unknown attribute found {}", attr.key()), } } assert_eq!(tx_result.tx, base64::decode("dHgyPXZhbHVl").unwrap()); @@ -1206,18 +1220,18 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 2); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key.as_str() { + match attr.key().as_str() { "creator" => { - assert_eq!(attr.value, "Cosmoshi Netowoko") + assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, - "key" => assert_eq!(attr.value, "tx3"), + "key" => assert_eq!(attr.value_str().unwrap(), "tx3"), "index_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, "noindex_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key), + _ => panic!("unknown attribute found {}", attr.key()), } } assert_eq!(tx_result.tx, base64::decode("dHgzPXZhbHVl").unwrap()); @@ -1238,18 +1252,18 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 2); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key.as_str() { + match attr.key().as_str() { "creator" => { - assert_eq!(attr.value, "Cosmoshi Netowoko") + assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, - "key" => assert_eq!(attr.value, "tx4"), + "key" => assert_eq!(attr.value_str().unwrap(), "tx4"), "index_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, "noindex_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key), + _ => panic!("unknown attribute found {}", attr.key()), } } assert_eq!(tx_result.tx, base64::decode("dHg0PXZhbHVl").unwrap()); diff --git a/rpc/tests/kvstore_fixtures/v0_38.rs b/rpc/tests/kvstore_fixtures/v0_38.rs index 6885e5ba7..e014f4735 100644 --- a/rpc/tests/kvstore_fixtures/v0_38.rs +++ b/rpc/tests/kvstore_fixtures/v0_38.rs @@ -503,21 +503,35 @@ fn incoming_fixtures() { assert!(result.tx_result.data.is_empty()); assert_eq!(result.tx_result.events.len(), 2); assert_eq!(result.tx_result.events[0].attributes.len(), 4); - assert_eq!(result.tx_result.events[0].attributes[0].key, "creator"); + assert_eq!(result.tx_result.events[0].attributes[0].key(), "creator"); assert_eq!( - result.tx_result.events[0].attributes[0].value, + result.tx_result.events[0].attributes[0] + .value_str() + .unwrap(), "Cosmoshi Netowoko" ); - assert_eq!(result.tx_result.events[0].attributes[1].key, "key"); - assert_eq!(result.tx_result.events[0].attributes[1].value, "commit-key"); - assert_eq!(result.tx_result.events[0].attributes[2].key, "index_key"); + assert_eq!(result.tx_result.events[0].attributes[1].key(), "key"); assert_eq!( - result.tx_result.events[0].attributes[2].value, + result.tx_result.events[0].attributes[1] + .value_str() + .unwrap(), + "commit-key" + ); + assert_eq!(result.tx_result.events[0].attributes[2].key(), "index_key"); + assert_eq!( + result.tx_result.events[0].attributes[2] + .value_str() + .unwrap(), "index is working" ); - assert_eq!(result.tx_result.events[0].attributes[3].key, "noindex_key"); assert_eq!( - result.tx_result.events[0].attributes[3].value, + result.tx_result.events[0].attributes[3].key(), + "noindex_key" + ); + assert_eq!( + result.tx_result.events[0].attributes[3] + .value_str() + .unwrap(), "index is working" ); assert_eq!(result.tx_result.events[0].kind, "app"); @@ -1101,18 +1115,18 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 2); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key.as_str() { + match attr.key().as_str() { "creator" => { - assert_eq!(attr.value, "Cosmoshi Netowoko") + assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, - "key" => assert_eq!(attr.value, "tx0"), + "key" => assert_eq!(attr.value_str().unwrap(), "tx0"), "index_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, "noindex_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key), + _ => panic!("unknown attribute found {}", attr.key()), } } assert_eq!(tx_result.tx, base64::decode("dHgwPXZhbHVl").unwrap()); @@ -1133,18 +1147,18 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 2); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key.as_str() { + match attr.key().as_str() { "creator" => { - assert_eq!(attr.value, "Cosmoshi Netowoko") + assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, - "key" => assert_eq!(attr.value, "tx1"), + "key" => assert_eq!(attr.value_str().unwrap(), "tx1"), "index_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, "noindex_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key), + _ => panic!("unknown attribute found {}", attr.key()), } } assert_eq!(tx_result.tx, base64::decode("dHgxPXZhbHVl").unwrap()); @@ -1166,18 +1180,18 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 2); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key.as_str() { + match attr.key().as_str() { "creator" => { - assert_eq!(attr.value, "Cosmoshi Netowoko") + assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, - "key" => assert_eq!(attr.value, "tx2"), + "key" => assert_eq!(attr.value_str().unwrap(), "tx2"), "index_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, "noindex_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key), + _ => panic!("unknown attribute found {}", attr.key()), } } assert_eq!(tx_result.tx, base64::decode("dHgyPXZhbHVl").unwrap()); @@ -1198,18 +1212,18 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 2); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key.as_str() { + match attr.key().as_str() { "creator" => { - assert_eq!(attr.value, "Cosmoshi Netowoko") + assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, - "key" => assert_eq!(attr.value, "tx3"), + "key" => assert_eq!(attr.value_str().unwrap(), "tx3"), "index_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, "noindex_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key), + _ => panic!("unknown attribute found {}", attr.key()), } } assert_eq!(tx_result.tx, base64::decode("dHgzPXZhbHVl").unwrap()); @@ -1230,18 +1244,18 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 2); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key.as_str() { + match attr.key().as_str() { "creator" => { - assert_eq!(attr.value, "Cosmoshi Netowoko") + assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, - "key" => assert_eq!(attr.value, "tx4"), + "key" => assert_eq!(attr.value_str().unwrap(), "tx4"), "index_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, "noindex_key" => { - assert_eq!(attr.value, "index is working") + assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key), + _ => panic!("unknown attribute found {}", attr.key()), } } assert_eq!(tx_result.tx, base64::decode("dHg0PXZhbHVl").unwrap()); diff --git a/tendermint/src/abci.rs b/tendermint/src/abci.rs index 2fae2e88d..379284ba8 100644 --- a/tendermint/src/abci.rs +++ b/tendermint/src/abci.rs @@ -53,6 +53,7 @@ pub use crate::v0_38::abci::response::{ ConsensusResponse, InfoResponse, MempoolResponse, SnapshotResponse, }; +pub use event::v0_34; pub use event::{Event, EventAttribute, EventAttributeIndexExt, TypedEvent}; #[doc(inline)] diff --git a/tendermint/src/abci/event.rs b/tendermint/src/abci/event.rs index 7a3cd3301..97905be31 100644 --- a/tendermint/src/abci/event.rs +++ b/tendermint/src/abci/event.rs @@ -1,7 +1,6 @@ use serde::{Deserialize, Serialize}; use crate::prelude::*; -use crate::serializers; /// An event that occurred while processing a request. /// @@ -25,6 +24,62 @@ pub struct Event { pub attributes: Vec, } +#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize, Hash)] +#[serde(untagged)] +pub enum EventAttribute { + /// EventAttribute value in TM34 is a byte array. + V034(v0_34::EventAttribute), + /// EventAttribute value in TM37 and later is a string. + V037(v0_37::EventAttribute), +} + +impl EventAttribute { + /// Access the `key` field common to all variants of the enum. + pub fn key(&self) -> &String { + match self { + EventAttribute::V034(attr) => &attr.key, + EventAttribute::V037(attr) => &attr.key, + } + } + + /// Access the `value` field common to all variants of the enum. Will return error if the value + /// is malformed UTF8. + pub fn value_str(&self) -> Result<&str, crate::Error> { + match self { + EventAttribute::V034(attr) => { + Ok(std::str::from_utf8(&attr.value) + .map_err(|e| crate::Error::parse(e.to_string()))?) + }, + EventAttribute::V037(attr) => Ok(&attr.value), + } + } + + /// Access the `value` field common to all variants of the enum. This is useful if you have + /// binary values for TM34. + pub fn value_as_bytes(&self) -> &[u8] { + match self { + EventAttribute::V034(attr) => &attr.value, + EventAttribute::V037(attr) => &attr.value.as_bytes(), + } + } + + /// Access the `index` field common to all variants of the enum. + pub fn index(&self) -> bool { + match self { + EventAttribute::V034(attr) => attr.index, + EventAttribute::V037(attr) => attr.index, + } + } + + /// Set `index` field common to all variants of the enum. + pub fn set_index(&mut self, index: bool) { + match self { + EventAttribute::V034(attr) => attr.index = index, + EventAttribute::V037(attr) => attr.index = index, + } + } +} + impl Event { /// Construct an event from generic data. /// @@ -111,47 +166,44 @@ where } } -/// A key-value pair describing an [`Event`]. -/// -/// Generic methods are provided for more ergonomic attribute construction, see -/// [`Event::new`] for details. -/// -/// [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#events) -#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Hash)] -pub struct EventAttribute { - /// The event key. - #[serde(with = "serializers::allow_null")] - pub key: String, - /// The event value. - #[serde(with = "serializers::allow_null")] - pub value: String, - /// Whether Tendermint's indexer should index this event. - /// - /// **This field is nondeterministic**. - pub index: bool, -} - impl EventAttribute { /// Checks whether `&self` is equal to `other`, ignoring the `index` field. pub fn eq_ignoring_index(&self, other: &Self) -> bool { - self.key == other.key && self.value == other.value + match (self, other) { + (EventAttribute::V034(a), EventAttribute::V034(b)) => { + a.key == b.key && a.value == b.value + }, + (EventAttribute::V037(a), EventAttribute::V037(b)) => { + a.key == b.key && a.value == b.value + }, + // Shouldn't happen, comparing event attributes from different versions + _ => false, + } } /// A variant of [`core::hash::Hash::hash`] that ignores the `index` field. pub fn hash_ignoring_index(&self, state: &mut H) { use core::hash::Hash; // Call the `Hash` impl on the (k,v) tuple to avoid prefix collision issues. - (&self.key, &self.value).hash(state); + match self { + EventAttribute::V034(attr) => { + (&attr.key, &attr.value).hash(state); + }, + EventAttribute::V037(attr) => { + (&attr.key, &attr.value).hash(state); + }, + } } } impl, V: Into> From<(K, V, bool)> for EventAttribute { fn from((key, value, index): (K, V, bool)) -> Self { - EventAttribute { + // TODO: support all versions + Self::V037(v0_37::EventAttribute { key: key.into(), value: value.into(), index, - } + }) } } @@ -201,13 +253,36 @@ impl, V: Into> From<(K, V)> for EventAttribute { // Protobuf conversions // ============================================================================= -mod v0_34 { - use super::{Event, EventAttribute}; +pub mod v0_34 { + use super::Event; use crate::prelude::*; + use crate::serializers; + use core::convert::{TryFrom, TryInto}; + use serde::{Deserialize, Serialize}; use tendermint_proto::v0_34::abci as pb; use tendermint_proto::Protobuf; + /// A key-value pair describing an [`Event`]. + /// + /// Generic methods are provided for more ergonomic attribute construction, see + /// [`Event::new`] for details. + /// + /// [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#events) + #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Hash)] + pub struct EventAttribute { + /// The event key. + #[serde(with = "serializers::allow_null")] + pub key: String, + /// The event value. + #[serde(with = "serializers::bytes::base64string")] + pub value: Vec, + /// Whether Tendermint's indexer should index this event. + /// + /// **This field is nondeterministic**. + pub index: bool, + } + impl From for pb::EventAttribute { fn from(event: EventAttribute) -> Self { Self { @@ -226,8 +301,7 @@ mod v0_34 { Ok(Self { key: String::from_utf8(event.key.to_vec()) .map_err(|e| crate::Error::parse(e.to_string()))?, - value: String::from_utf8(event.value.to_vec()) - .map_err(|e| crate::Error::parse(e.to_string()))?, + value: event.value.to_vec(), index: event.index, }) } @@ -239,7 +313,16 @@ mod v0_34 { fn from(event: Event) -> Self { Self { r#type: event.kind, - attributes: event.attributes.into_iter().map(Into::into).collect(), + attributes: event + .attributes + .into_iter() + .filter_map(|t| { + let super::EventAttribute::V034(ea) = t else { + return None; + }; + Some(ea.into()) + }) + .collect(), } } } @@ -254,7 +337,10 @@ mod v0_34 { .attributes .into_iter() .map(TryInto::try_into) - .collect::>()?, + .collect::, _>>()? + .into_iter() + .map(super::EventAttribute::V034) + .collect(), }) } } @@ -263,12 +349,35 @@ mod v0_34 { } mod v0_37 { - use super::{Event, EventAttribute}; + use super::Event; use crate::prelude::*; + use crate::serializers; + use core::convert::{TryFrom, TryInto}; + use serde::{Deserialize, Serialize}; use tendermint_proto::v0_37::abci as pb; use tendermint_proto::Protobuf; + /// A key-value pair describing an [`Event`]. + /// + /// Generic methods are provided for more ergonomic attribute construction, see + /// [`Event::new`] for details. + /// + /// [ABCI documentation](https://docs.tendermint.com/master/spec/abci/abci.html#events) + #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Hash)] + pub struct EventAttribute { + /// The event key. + #[serde(with = "serializers::allow_null")] + pub key: String, + /// The event value. + #[serde(with = "serializers::allow_null")] + pub value: String, + /// Whether Tendermint's indexer should index this event. + /// + /// **This field is nondeterministic**. + pub index: bool, + } + impl From for pb::EventAttribute { fn from(event: EventAttribute) -> Self { Self { @@ -297,7 +406,16 @@ mod v0_37 { fn from(event: Event) -> Self { Self { r#type: event.kind, - attributes: event.attributes.into_iter().map(Into::into).collect(), + attributes: event + .attributes + .into_iter() + .filter_map(|t| { + let super::EventAttribute::V037(ea) = t else { + return None; + }; + Some(ea.into()) + }) + .collect(), } } } @@ -312,7 +430,10 @@ mod v0_37 { .attributes .into_iter() .map(TryInto::try_into) - .collect::>()?, + .collect::, _>>()? + .into_iter() + .map(super::EventAttribute::V037) + .collect(), }) } } @@ -321,12 +442,14 @@ mod v0_37 { } mod v0_38 { - use super::{Event, EventAttribute}; + use super::Event; use crate::prelude::*; use tendermint_proto::v0_38::abci as pb; use tendermint_proto::Protobuf; + pub use super::v0_37::EventAttribute; + impl From for pb::EventAttribute { fn from(event: EventAttribute) -> Self { Self { @@ -355,7 +478,16 @@ mod v0_38 { fn from(event: Event) -> Self { Self { r#type: event.kind, - attributes: event.attributes.into_iter().map(Into::into).collect(), + attributes: event + .attributes + .into_iter() + .filter_map(|t| { + let super::EventAttribute::V037(ea) = t else { + return None; + }; + Some(ea.into()) + }) + .collect(), } } } @@ -370,7 +502,10 @@ mod v0_38 { .attributes .into_iter() .map(TryInto::try_into) - .collect::>()?, + .collect::, _>>()? + .into_iter() + .map(super::EventAttribute::V037) + .collect(), }) } } @@ -434,15 +569,19 @@ mod tests { let a = event .attributes .iter() - .find(|attr| attr.key == "a") + .find(|attr| attr.key() == "a") .ok_or(()) - .and_then(|attr| serde_json::from_str(&attr.value).map_err(|_| ()))?; + .and_then(|attr| { + serde_json::from_str(&attr.value_str().unwrap()).map_err(|_| ()) + })?; let b = event .attributes .iter() - .find(|attr| attr.key == "b") + .find(|attr| attr.key() == "b") .ok_or(()) - .and_then(|attr| serde_json::from_str(&attr.value).map_err(|_| ()))?; + .and_then(|attr| { + serde_json::from_str(&attr.value_str().unwrap()).map_err(|_| ()) + })?; Ok(MyEvent { a, b }) } @@ -459,8 +598,8 @@ mod tests { // e2 is like e1 but with different indexing. let e2 = { let mut e = e1.clone(); - e.attributes[0].index = false; - e.attributes[1].index = false; + e.attributes[0].set_index(false); + e.attributes[1].set_index(false); e }; From f0390f391a0f8bc12096c1f582d6e9ee5557144d Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Fri, 5 Apr 2024 10:41:08 +0200 Subject: [PATCH 02/16] Fix clippy warnings --- tendermint/src/abci/event.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tendermint/src/abci/event.rs b/tendermint/src/abci/event.rs index 97905be31..dd0175b1e 100644 --- a/tendermint/src/abci/event.rs +++ b/tendermint/src/abci/event.rs @@ -59,7 +59,7 @@ impl EventAttribute { pub fn value_as_bytes(&self) -> &[u8] { match self { EventAttribute::V034(attr) => &attr.value, - EventAttribute::V037(attr) => &attr.value.as_bytes(), + EventAttribute::V037(attr) => attr.value.as_bytes(), } } @@ -572,7 +572,7 @@ mod tests { .find(|attr| attr.key() == "a") .ok_or(()) .and_then(|attr| { - serde_json::from_str(&attr.value_str().unwrap()).map_err(|_| ()) + serde_json::from_str(attr.value_str().unwrap()).map_err(|_| ()) })?; let b = event .attributes @@ -580,7 +580,7 @@ mod tests { .find(|attr| attr.key() == "b") .ok_or(()) .and_then(|attr| { - serde_json::from_str(&attr.value_str().unwrap()).map_err(|_| ()) + serde_json::from_str(attr.value_str().unwrap()).map_err(|_| ()) })?; Ok(MyEvent { a, b }) From 47cdffe1b019e7bb517d26c97d183d882e293a31 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Fri, 5 Apr 2024 10:41:23 +0200 Subject: [PATCH 03/16] Rename `value_as_bytes` to `value_bytes` --- rpc/src/dialect/v0_34.rs | 2 +- tendermint/src/abci/event.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rpc/src/dialect/v0_34.rs b/rpc/src/dialect/v0_34.rs index 0c0f8b621..4c382ed23 100644 --- a/rpc/src/dialect/v0_34.rs +++ b/rpc/src/dialect/v0_34.rs @@ -73,7 +73,7 @@ impl From for EventAttribute { fn from(msg: abci::EventAttribute) -> Self { Self { key: msg.key().clone(), - value: msg.value_as_bytes().to_vec(), + value: msg.value_bytes().to_vec(), index: msg.index(), } } diff --git a/tendermint/src/abci/event.rs b/tendermint/src/abci/event.rs index dd0175b1e..94071e689 100644 --- a/tendermint/src/abci/event.rs +++ b/tendermint/src/abci/event.rs @@ -56,7 +56,7 @@ impl EventAttribute { /// Access the `value` field common to all variants of the enum. This is useful if you have /// binary values for TM34. - pub fn value_as_bytes(&self) -> &[u8] { + pub fn value_bytes(&self) -> &[u8] { match self { EventAttribute::V034(attr) => &attr.value, EventAttribute::V037(attr) => attr.value.as_bytes(), From 0d93c608cc3f6824a9284c86f5495eab0e40e3f3 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Fri, 5 Apr 2024 11:21:49 +0200 Subject: [PATCH 04/16] Change v0.34 event attribute key type to `Vec` --- rpc/src/dialect/v0_34.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/rpc/src/dialect/v0_34.rs b/rpc/src/dialect/v0_34.rs index 4c382ed23..12a9e6a2b 100644 --- a/rpc/src/dialect/v0_34.rs +++ b/rpc/src/dialect/v0_34.rs @@ -44,15 +44,17 @@ pub struct EventAttribute { /// The event key. #[serde( serialize_with = "base64string::serialize", - deserialize_with = "base64string::deserialize_to_string" + deserialize_with = "base64string::deserialize" )] - pub key: String, + pub key: Vec, + /// The event value. #[serde( serialize_with = "base64string::serialize", deserialize_with = "base64string::deserialize" )] pub value: Vec, + /// Whether Tendermint's indexer should index this event. /// /// **This field is nondeterministic**. @@ -72,7 +74,7 @@ impl From for abci::EventAttribute { impl From for EventAttribute { fn from(msg: abci::EventAttribute) -> Self { Self { - key: msg.key().clone(), + key: msg.key_bytes().to_vec(), value: msg.value_bytes().to_vec(), index: msg.index(), } From 755a1039870ec74c8546cac226ce97630d9e5989 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Fri, 5 Apr 2024 11:22:47 +0200 Subject: [PATCH 05/16] Update doc comments --- tendermint/src/abci/event.rs | 43 ++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/tendermint/src/abci/event.rs b/tendermint/src/abci/event.rs index 94071e689..4373caa0d 100644 --- a/tendermint/src/abci/event.rs +++ b/tendermint/src/abci/event.rs @@ -20,10 +20,23 @@ pub struct Event { /// with Rust types and follow Rust conventions. #[serde(rename = "type")] pub kind: String, + /// A list of [`EventAttribute`]s describing the event. pub attributes: Vec, } +/// The attributes of an Event consist of a key, a value, and an index flag. +/// The index flag notifies the Tendermint indexer to index the attribute. +/// The value of the index flag is non-deterministic and may vary across different nodes in the network. +/// +/// Before Tendermint v0.37, the key and value can contain arbitrary byte arrays. +/// Since Tendermint v0.37, the key and value are defined to be valud UTF-8 encoded strings. +/// +/// IMPORTANT: The order of the two variants below is significant and nmust not be changed. +/// The `EventAttribute` enum is serialized and deserialized using the `untagged` attribute, +/// meaning that the first variant is tried first when deserializing, if that fails +/// then the second variant is tried. This allows us to deserialize v0.37+ events which +/// are vald UTF-8 strings, and fall back to deserializing v0.34 events which are arbitrary byte arrays. #[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize, Hash)] #[serde(untagged)] pub enum EventAttribute { @@ -34,28 +47,38 @@ pub enum EventAttribute { } impl EventAttribute { - /// Access the `key` field common to all variants of the enum. - pub fn key(&self) -> &String { + /// Access the `key` field common to all variants of the enum as a string. + /// Will return error if the value is malformed UTF8. + pub fn key_str(&self) -> Result<&str, crate::Error> { + match self { + EventAttribute::V034(attr) => { + std::str::from_utf8(&attr.key).map_err(|e| crate::Error::parse(e.to_string())) + }, + EventAttribute::V037(attr) => Ok(&attr.key), + } + } + + /// Access the `key` field common to all variants of the enum as bytes. + pub fn key_bytes(&self) -> &[u8] { match self { EventAttribute::V034(attr) => &attr.key, - EventAttribute::V037(attr) => &attr.key, + EventAttribute::V037(attr) => attr.key.as_bytes(), } } - /// Access the `value` field common to all variants of the enum. Will return error if the value - /// is malformed UTF8. + /// Access the `value` field common to all variants of the enum as a string. + /// Will return error if the value is malformed UTF8. pub fn value_str(&self) -> Result<&str, crate::Error> { match self { EventAttribute::V034(attr) => { - Ok(std::str::from_utf8(&attr.value) - .map_err(|e| crate::Error::parse(e.to_string()))?) + std::str::from_utf8(&attr.value).map_err(|e| crate::Error::parse(e.to_string())) }, EventAttribute::V037(attr) => Ok(&attr.value), } } - /// Access the `value` field common to all variants of the enum. This is useful if you have - /// binary values for TM34. + /// Access the `value` field common to all variants of the enum as bytes. + /// This is useful if you have binary values for TM34. pub fn value_bytes(&self) -> &[u8] { match self { EventAttribute::V034(attr) => &attr.value, @@ -369,9 +392,11 @@ mod v0_37 { /// The event key. #[serde(with = "serializers::allow_null")] pub key: String, + /// The event value. #[serde(with = "serializers::allow_null")] pub value: String, + /// Whether Tendermint's indexer should index this event. /// /// **This field is nondeterministic**. From f9b409678c7a4e5d4b8402aa4f7e8fcd89254dbf Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Fri, 5 Apr 2024 11:24:26 +0200 Subject: [PATCH 06/16] !fixup 0d93c608 --- tendermint/src/abci/event.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tendermint/src/abci/event.rs b/tendermint/src/abci/event.rs index 4373caa0d..0ea50ca80 100644 --- a/tendermint/src/abci/event.rs +++ b/tendermint/src/abci/event.rs @@ -295,11 +295,13 @@ pub mod v0_34 { #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Hash)] pub struct EventAttribute { /// The event key. - #[serde(with = "serializers::allow_null")] - pub key: String, + #[serde(with = "serializers::bytes::base64string")] + pub key: Vec, + /// The event value. #[serde(with = "serializers::bytes::base64string")] pub value: Vec, + /// Whether Tendermint's indexer should index this event. /// /// **This field is nondeterministic**. @@ -320,10 +322,8 @@ pub mod v0_34 { type Error = crate::Error; fn try_from(event: pb::EventAttribute) -> Result { - // We insist that keys and values are strings, like tm 0.35 did. Ok(Self { - key: String::from_utf8(event.key.to_vec()) - .map_err(|e| crate::Error::parse(e.to_string()))?, + key: event.value.to_vec(), value: event.value.to_vec(), index: event.index, }) @@ -594,7 +594,7 @@ mod tests { let a = event .attributes .iter() - .find(|attr| attr.key() == "a") + .find(|attr| attr.key_bytes() == b"a") .ok_or(()) .and_then(|attr| { serde_json::from_str(attr.value_str().unwrap()).map_err(|_| ()) @@ -602,7 +602,7 @@ mod tests { let b = event .attributes .iter() - .find(|attr| attr.key() == "b") + .find(|attr| attr.key_bytes() == b"b") .ok_or(()) .and_then(|attr| { serde_json::from_str(attr.value_str().unwrap()).map_err(|_| ()) From 97bb9922c0c29e3e81db55077f1d396b44d4c34e Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Fri, 5 Apr 2024 11:24:51 +0200 Subject: [PATCH 07/16] Fix deserialization of untagged `EventAttribute` --- tendermint/src/abci/event.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tendermint/src/abci/event.rs b/tendermint/src/abci/event.rs index 0ea50ca80..e5ef5b1b9 100644 --- a/tendermint/src/abci/event.rs +++ b/tendermint/src/abci/event.rs @@ -40,10 +40,11 @@ pub struct Event { #[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize, Hash)] #[serde(untagged)] pub enum EventAttribute { - /// EventAttribute value in TM34 is a byte array. - V034(v0_34::EventAttribute), - /// EventAttribute value in TM37 and later is a string. + /// EventAttribute keys and values in TM37 and later are plain strings. V037(v0_37::EventAttribute), + + /// EventAttribute keys and values in TM34 are base64-encoded strings. + V034(v0_34::EventAttribute), } impl EventAttribute { From d03a5036c4ce15475ab96b2401966384320dd2de Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Fri, 5 Apr 2024 11:25:01 +0200 Subject: [PATCH 08/16] Fix tests --- rpc/tests/kvstore_fixtures/v0_34.rs | 42 ++++++++++++++++------------- rpc/tests/kvstore_fixtures/v0_37.rs | 42 ++++++++++++++++------------- rpc/tests/kvstore_fixtures/v0_38.rs | 36 ++++++++++++++----------- 3 files changed, 69 insertions(+), 51 deletions(-) diff --git a/rpc/tests/kvstore_fixtures/v0_34.rs b/rpc/tests/kvstore_fixtures/v0_34.rs index c307bf790..68b6435cb 100644 --- a/rpc/tests/kvstore_fixtures/v0_34.rs +++ b/rpc/tests/kvstore_fixtures/v0_34.rs @@ -509,21 +509,27 @@ fn incoming_fixtures() { assert!(result.tx_result.data.is_empty()); assert_eq!(result.tx_result.events.len(), 1); assert_eq!(result.tx_result.events[0].attributes.len(), 4); - assert_eq!(result.tx_result.events[0].attributes[0].key(), "creator"); + assert_eq!( + result.tx_result.events[0].attributes[0].key_bytes(), + b"creator" + ); assert_eq!( result.tx_result.events[0].attributes[0] .value_str() .unwrap(), "Cosmoshi Netowoko" ); - assert_eq!(result.tx_result.events[0].attributes[1].key(), "key"); + assert_eq!(result.tx_result.events[0].attributes[1].key_bytes(), b"key"); assert_eq!( result.tx_result.events[0].attributes[1] .value_str() .unwrap(), "commit-key" ); - assert_eq!(result.tx_result.events[0].attributes[2].key(), "index_key"); + assert_eq!( + result.tx_result.events[0].attributes[2].key_bytes(), + b"index_key" + ); assert_eq!( result.tx_result.events[0].attributes[2] .value_str() @@ -531,8 +537,8 @@ fn incoming_fixtures() { "index is working" ); assert_eq!( - result.tx_result.events[0].attributes[3].key(), - "noindex_key" + result.tx_result.events[0].attributes[3].key_bytes(), + b"noindex_key" ); assert_eq!( result.tx_result.events[0].attributes[3] @@ -922,13 +928,13 @@ fn incoming_fixtures() { assert_eq!(rbb.events.len(), 2); assert_eq!(rbb.events[0].kind, "transfer"); assert_eq!(rbb.events[0].attributes.len(), 2); - assert_eq!(rbb.events[0].attributes[0].key(), "recipient"); + assert_eq!(rbb.events[0].attributes[0].key_bytes(), b"recipient"); assert_eq!( rbb.events[0].attributes[0].value_str().unwrap(), "cosmos17xpfvakm2amg962yls6f84z3kell8c5lserqta" ); assert!(rbb.events[0].attributes[0].index()); - assert_eq!(rbb.events[0].attributes[1].key(), "sender"); + assert_eq!(rbb.events[0].attributes[1].key_bytes(), b"sender"); assert_eq!( rbb.events[0].attributes[1].value_str().unwrap(), "cosmos1m3h30wlvsf8llruxtpukdvsy0km2kum8g38c8q" @@ -936,7 +942,7 @@ fn incoming_fixtures() { assert!(!rbb.events[0].attributes[1].index()); assert_eq!(rbb.events[1].kind, "message"); assert_eq!(rbb.events[1].attributes.len(), 1); - assert_eq!(rbb.events[1].attributes[0].key(), "sender"); + assert_eq!(rbb.events[1].attributes[0].key_bytes(), b"sender"); assert_eq!( rbb.events[1].attributes[0].value_str().unwrap(), "cosmos1m3h30wlvsf8llruxtpukdvsy0km2kum8g38c8q" @@ -1129,7 +1135,7 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 1); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key().as_str() { + match attr.key_str().unwrap() { "creator" => { assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, @@ -1140,7 +1146,7 @@ fn incoming_fixtures() { "noindex_key" => { assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key()), + other => panic!("unknown attribute found {other}"), } } assert_eq!(tx_result.tx, base64::decode("dHgwPXZhbHVl").unwrap()); @@ -1161,7 +1167,7 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 1); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key().as_str() { + match attr.key_str().unwrap() { "creator" => { assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, @@ -1172,7 +1178,7 @@ fn incoming_fixtures() { "noindex_key" => { assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key()), + other => panic!("unknown attribute found {other}"), } } assert_eq!(tx_result.tx, base64::decode("dHgxPXZhbHVl").unwrap()); @@ -1194,7 +1200,7 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 1); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key().as_str() { + match attr.key_str().unwrap() { "creator" => { assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, @@ -1205,7 +1211,7 @@ fn incoming_fixtures() { "noindex_key" => { assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key()), + other => panic!("unknown attribute found {other}"), } } assert_eq!(tx_result.tx, base64::decode("dHgyPXZhbHVl").unwrap()); @@ -1226,7 +1232,7 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 1); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key().as_str() { + match attr.key_str().unwrap() { "creator" => { assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, @@ -1237,7 +1243,7 @@ fn incoming_fixtures() { "noindex_key" => { assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key()), + other => panic!("unknown attribute found {other}"), } } assert_eq!(tx_result.tx, base64::decode("dHgzPXZhbHVl").unwrap()); @@ -1258,7 +1264,7 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 1); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key().as_str() { + match attr.key_str().unwrap() { "creator" => { assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, @@ -1269,7 +1275,7 @@ fn incoming_fixtures() { "noindex_key" => { assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key()), + other => panic!("unknown attribute found {other}"), } } assert_eq!(tx_result.tx, base64::decode("dHg0PXZhbHVl").unwrap()); diff --git a/rpc/tests/kvstore_fixtures/v0_37.rs b/rpc/tests/kvstore_fixtures/v0_37.rs index 3bdf8b43d..5efd62e78 100644 --- a/rpc/tests/kvstore_fixtures/v0_37.rs +++ b/rpc/tests/kvstore_fixtures/v0_37.rs @@ -503,21 +503,27 @@ fn incoming_fixtures() { assert!(result.tx_result.data.is_empty()); assert_eq!(result.tx_result.events.len(), 2); assert_eq!(result.tx_result.events[0].attributes.len(), 4); - assert_eq!(result.tx_result.events[0].attributes[0].key(), "creator"); + assert_eq!( + result.tx_result.events[0].attributes[0].key_bytes(), + b"creator" + ); assert_eq!( result.tx_result.events[0].attributes[0] .value_str() .unwrap(), "Cosmoshi Netowoko" ); - assert_eq!(result.tx_result.events[0].attributes[1].key(), "key"); + assert_eq!(result.tx_result.events[0].attributes[1].key_bytes(), b"key"); assert_eq!( result.tx_result.events[0].attributes[1] .value_str() .unwrap(), "commit-key" ); - assert_eq!(result.tx_result.events[0].attributes[2].key(), "index_key"); + assert_eq!( + result.tx_result.events[0].attributes[2].key_bytes(), + b"index_key" + ); assert_eq!( result.tx_result.events[0].attributes[2] .value_str() @@ -525,8 +531,8 @@ fn incoming_fixtures() { "index is working" ); assert_eq!( - result.tx_result.events[0].attributes[3].key(), - "noindex_key" + result.tx_result.events[0].attributes[3].key_bytes(), + b"noindex_key" ); assert_eq!( result.tx_result.events[0].attributes[3] @@ -916,13 +922,13 @@ fn incoming_fixtures() { assert_eq!(rbb.events.len(), 2); assert_eq!(rbb.events[0].kind, "transfer"); assert_eq!(rbb.events[0].attributes.len(), 2); - assert_eq!(rbb.events[0].attributes[0].key(), "recipient"); + assert_eq!(rbb.events[0].attributes[0].key_bytes(), b"recipient"); assert_eq!( rbb.events[0].attributes[0].value_str().unwrap(), "cosmos17xpfvakm2amg962yls6f84z3kell8c5lserqta" ); assert!(rbb.events[0].attributes[0].index()); - assert_eq!(rbb.events[0].attributes[1].key(), "sender"); + assert_eq!(rbb.events[0].attributes[1].key_bytes(), b"sender"); assert_eq!( rbb.events[0].attributes[1].value_str().unwrap(), "cosmos1m3h30wlvsf8llruxtpukdvsy0km2kum8g38c8q" @@ -930,7 +936,7 @@ fn incoming_fixtures() { assert!(!rbb.events[0].attributes[1].index()); assert_eq!(rbb.events[1].kind, "message"); assert_eq!(rbb.events[1].attributes.len(), 1); - assert_eq!(rbb.events[1].attributes[0].key(), "sender"); + assert_eq!(rbb.events[1].attributes[0].key_bytes(), b"sender"); assert_eq!( rbb.events[1].attributes[0].value_str().unwrap(), "cosmos1m3h30wlvsf8llruxtpukdvsy0km2kum8g38c8q" @@ -1123,7 +1129,7 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 2); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key().as_str() { + match attr.key_str().unwrap() { "creator" => { assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, @@ -1134,7 +1140,7 @@ fn incoming_fixtures() { "noindex_key" => { assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key()), + other => panic!("unknown attribute found {other}"), } } assert_eq!(tx_result.tx, base64::decode("dHgwPXZhbHVl").unwrap()); @@ -1155,7 +1161,7 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 2); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key().as_str() { + match attr.key_str().unwrap() { "creator" => { assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, @@ -1166,7 +1172,7 @@ fn incoming_fixtures() { "noindex_key" => { assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key()), + other => panic!("unknown attribute found {other}"), } } assert_eq!(tx_result.tx, base64::decode("dHgxPXZhbHVl").unwrap()); @@ -1188,7 +1194,7 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 2); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key().as_str() { + match attr.key_str().unwrap() { "creator" => { assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, @@ -1199,7 +1205,7 @@ fn incoming_fixtures() { "noindex_key" => { assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key()), + other => panic!("unknown attribute found {other}"), } } assert_eq!(tx_result.tx, base64::decode("dHgyPXZhbHVl").unwrap()); @@ -1220,7 +1226,7 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 2); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key().as_str() { + match attr.key_str().unwrap() { "creator" => { assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, @@ -1231,7 +1237,7 @@ fn incoming_fixtures() { "noindex_key" => { assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key()), + other => panic!("unknown attribute found {other}"), } } assert_eq!(tx_result.tx, base64::decode("dHgzPXZhbHVl").unwrap()); @@ -1252,7 +1258,7 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 2); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key().as_str() { + match dbg!(attr).key_str().unwrap() { "creator" => { assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, @@ -1263,7 +1269,7 @@ fn incoming_fixtures() { "noindex_key" => { assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key()), + other => panic!("unknown attribute found {other}"), } } assert_eq!(tx_result.tx, base64::decode("dHg0PXZhbHVl").unwrap()); diff --git a/rpc/tests/kvstore_fixtures/v0_38.rs b/rpc/tests/kvstore_fixtures/v0_38.rs index e014f4735..0a8a6318b 100644 --- a/rpc/tests/kvstore_fixtures/v0_38.rs +++ b/rpc/tests/kvstore_fixtures/v0_38.rs @@ -503,21 +503,27 @@ fn incoming_fixtures() { assert!(result.tx_result.data.is_empty()); assert_eq!(result.tx_result.events.len(), 2); assert_eq!(result.tx_result.events[0].attributes.len(), 4); - assert_eq!(result.tx_result.events[0].attributes[0].key(), "creator"); + assert_eq!( + result.tx_result.events[0].attributes[0].key_bytes(), + b"creator" + ); assert_eq!( result.tx_result.events[0].attributes[0] .value_str() .unwrap(), "Cosmoshi Netowoko" ); - assert_eq!(result.tx_result.events[0].attributes[1].key(), "key"); + assert_eq!(result.tx_result.events[0].attributes[1].key_bytes(), b"key"); assert_eq!( result.tx_result.events[0].attributes[1] .value_str() .unwrap(), "commit-key" ); - assert_eq!(result.tx_result.events[0].attributes[2].key(), "index_key"); + assert_eq!( + result.tx_result.events[0].attributes[2].key_bytes(), + b"index_key" + ); assert_eq!( result.tx_result.events[0].attributes[2] .value_str() @@ -525,8 +531,8 @@ fn incoming_fixtures() { "index is working" ); assert_eq!( - result.tx_result.events[0].attributes[3].key(), - "noindex_key" + result.tx_result.events[0].attributes[3].key_bytes(), + b"noindex_key" ); assert_eq!( result.tx_result.events[0].attributes[3] @@ -1115,7 +1121,7 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 2); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key().as_str() { + match attr.key_str().unwrap() { "creator" => { assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, @@ -1126,7 +1132,7 @@ fn incoming_fixtures() { "noindex_key" => { assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key()), + other => panic!("unknown attribute found {other}"), } } assert_eq!(tx_result.tx, base64::decode("dHgwPXZhbHVl").unwrap()); @@ -1147,7 +1153,7 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 2); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key().as_str() { + match attr.key_str().unwrap() { "creator" => { assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, @@ -1158,7 +1164,7 @@ fn incoming_fixtures() { "noindex_key" => { assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key()), + other => panic!("unknown attribute found {other}"), } } assert_eq!(tx_result.tx, base64::decode("dHgxPXZhbHVl").unwrap()); @@ -1180,7 +1186,7 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 2); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key().as_str() { + match attr.key_str().unwrap() { "creator" => { assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, @@ -1191,7 +1197,7 @@ fn incoming_fixtures() { "noindex_key" => { assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key()), + other => panic!("unknown attribute found {other}"), } } assert_eq!(tx_result.tx, base64::decode("dHgyPXZhbHVl").unwrap()); @@ -1212,7 +1218,7 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 2); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key().as_str() { + match attr.key_str().unwrap() { "creator" => { assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, @@ -1223,7 +1229,7 @@ fn incoming_fixtures() { "noindex_key" => { assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key()), + other => panic!("unknown attribute found {other}"), } } assert_eq!(tx_result.tx, base64::decode("dHgzPXZhbHVl").unwrap()); @@ -1244,7 +1250,7 @@ fn incoming_fixtures() { assert_eq!(tx_result.result.events.len(), 2); assert_eq!(tx_result.result.events[0].kind, "app"); for attr in &tx_result.result.events[0].attributes { - match attr.key().as_str() { + match attr.key_str().unwrap() { "creator" => { assert_eq!(attr.value_str().unwrap(), "Cosmoshi Netowoko") }, @@ -1255,7 +1261,7 @@ fn incoming_fixtures() { "noindex_key" => { assert_eq!(attr.value_str().unwrap(), "index is working") }, - _ => panic!("unknown attribute found {}", attr.key()), + other => panic!("unknown attribute found {other}"), } } assert_eq!(tx_result.tx, base64::decode("dHg0PXZhbHVl").unwrap()); From 53f39e1376989c79c4298a576e226da20dfb626c Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Fri, 5 Apr 2024 11:28:43 +0200 Subject: [PATCH 09/16] Update changelog entry --- .../breaking-changes/1405-change-event-attribute-value.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.changelog/unreleased/breaking-changes/1405-change-event-attribute-value.md b/.changelog/unreleased/breaking-changes/1405-change-event-attribute-value.md index 9ccdc2555..284df5f58 100644 --- a/.changelog/unreleased/breaking-changes/1405-change-event-attribute-value.md +++ b/.changelog/unreleased/breaking-changes/1405-change-event-attribute-value.md @@ -1,4 +1,3 @@ -- `[tendermint]` Change `EventAttribute` `value` from `String` to `Vec` for - TM34. `key`, `value` and `index` now have to be called through `key()`, - `value_str()` and `index()` to support both `Vec` and `String`. +- `[tendermint]` Change `EventAttribute`'s `key` and `value` fields from `String` to `Vec` for Tendermint v0.34, as enforced by the Protobuf schema for Tendermint v0.34. + `tendermint::abci::EventAttribute` is now an enum, to account for version 0.34 and 0.37+, therefore the `key`, `value` and `index` fields now have to be retrieved through the `key_str()`/`key_bytes`, `value_str()`/`value_bytes()` and `index()` methods. ([\#1400](https://github.com/informalsystems/tendermint-rs/issues/1400)). From 8577e85bce7ca6d100ec4e8af4eb2bc106a91942 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Fri, 5 Apr 2024 11:39:27 +0200 Subject: [PATCH 10/16] Remove TODO --- tendermint/src/abci/event.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/tendermint/src/abci/event.rs b/tendermint/src/abci/event.rs index e5ef5b1b9..5ec45db31 100644 --- a/tendermint/src/abci/event.rs +++ b/tendermint/src/abci/event.rs @@ -222,7 +222,6 @@ impl EventAttribute { impl, V: Into> From<(K, V, bool)> for EventAttribute { fn from((key, value, index): (K, V, bool)) -> Self { - // TODO: support all versions Self::V037(v0_37::EventAttribute { key: key.into(), value: value.into(), From 7a791b0bccc9ae0658770f81e0ecc75362d66eb8 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Fri, 5 Apr 2024 11:43:19 +0200 Subject: [PATCH 11/16] Fix no_std compat --- tendermint/src/abci/event.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tendermint/src/abci/event.rs b/tendermint/src/abci/event.rs index 5ec45db31..1c49b678d 100644 --- a/tendermint/src/abci/event.rs +++ b/tendermint/src/abci/event.rs @@ -53,7 +53,7 @@ impl EventAttribute { pub fn key_str(&self) -> Result<&str, crate::Error> { match self { EventAttribute::V034(attr) => { - std::str::from_utf8(&attr.key).map_err(|e| crate::Error::parse(e.to_string())) + core::str::from_utf8(&attr.key).map_err(|e| crate::Error::parse(e.to_string())) }, EventAttribute::V037(attr) => Ok(&attr.key), } @@ -72,7 +72,7 @@ impl EventAttribute { pub fn value_str(&self) -> Result<&str, crate::Error> { match self { EventAttribute::V034(attr) => { - std::str::from_utf8(&attr.value).map_err(|e| crate::Error::parse(e.to_string())) + core::str::from_utf8(&attr.value).map_err(|e| crate::Error::parse(e.to_string())) }, EventAttribute::V037(attr) => Ok(&attr.value), } From 93e52722b5c9427ba58c5ac3668b27a8f5ca9b78 Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Fri, 5 Apr 2024 11:46:36 +0200 Subject: [PATCH 12/16] Fix warnings on nightly --- tendermint/src/abci/event.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/tendermint/src/abci/event.rs b/tendermint/src/abci/event.rs index 1c49b678d..6eeacff85 100644 --- a/tendermint/src/abci/event.rs +++ b/tendermint/src/abci/event.rs @@ -280,7 +280,6 @@ pub mod v0_34 { use super::Event; use crate::prelude::*; use crate::serializers; - use core::convert::{TryFrom, TryInto}; use serde::{Deserialize, Serialize}; use tendermint_proto::v0_34::abci as pb; @@ -375,7 +374,6 @@ mod v0_37 { use super::Event; use crate::prelude::*; use crate::serializers; - use core::convert::{TryFrom, TryInto}; use serde::{Deserialize, Serialize}; use tendermint_proto::v0_37::abci as pb; From 0cbdc493e10c479ab7219ab478a203db0e3e35c0 Mon Sep 17 00:00:00 2001 From: Fabien Penso Date: Mon, 8 Apr 2024 12:33:58 +0200 Subject: [PATCH 13/16] Update tendermint/src/abci/event.rs Co-authored-by: Erwan Or --- tendermint/src/abci/event.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tendermint/src/abci/event.rs b/tendermint/src/abci/event.rs index 6eeacff85..d58da0ddc 100644 --- a/tendermint/src/abci/event.rs +++ b/tendermint/src/abci/event.rs @@ -32,7 +32,7 @@ pub struct Event { /// Before Tendermint v0.37, the key and value can contain arbitrary byte arrays. /// Since Tendermint v0.37, the key and value are defined to be valud UTF-8 encoded strings. /// -/// IMPORTANT: The order of the two variants below is significant and nmust not be changed. +/// IMPORTANT: The order of the two variants below is significant and must not be changed. /// The `EventAttribute` enum is serialized and deserialized using the `untagged` attribute, /// meaning that the first variant is tried first when deserializing, if that fails /// then the second variant is tried. This allows us to deserialize v0.37+ events which From 0afbd1a5017e02c99f4abb22f92c8f6612a11950 Mon Sep 17 00:00:00 2001 From: Fabien Penso Date: Mon, 8 Apr 2024 12:34:04 +0200 Subject: [PATCH 14/16] Update tendermint/src/abci/event.rs Co-authored-by: Erwan Or --- tendermint/src/abci/event.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tendermint/src/abci/event.rs b/tendermint/src/abci/event.rs index d58da0ddc..0e32c2bc4 100644 --- a/tendermint/src/abci/event.rs +++ b/tendermint/src/abci/event.rs @@ -30,7 +30,7 @@ pub struct Event { /// The value of the index flag is non-deterministic and may vary across different nodes in the network. /// /// Before Tendermint v0.37, the key and value can contain arbitrary byte arrays. -/// Since Tendermint v0.37, the key and value are defined to be valud UTF-8 encoded strings. +/// Since Tendermint v0.37, the key and value are defined to be valid UTF-8 encoded strings. /// /// IMPORTANT: The order of the two variants below is significant and must not be changed. /// The `EventAttribute` enum is serialized and deserialized using the `untagged` attribute, From 6f056eac732472c27c3bdf6cd3bfff78975f874e Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Mon, 22 Apr 2024 08:24:17 +0200 Subject: [PATCH 15/16] Formatting --- tendermint/src/abci/event.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/tendermint/src/abci/event.rs b/tendermint/src/abci/event.rs index b441cea5a..92aef5edb 100644 --- a/tendermint/src/abci/event.rs +++ b/tendermint/src/abci/event.rs @@ -587,7 +587,6 @@ mod tests { return Err(()); } - let a = event .attributes .iter() From 71ac8c1b72059613c75a0784d5c5019aedd0390d Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Mon, 22 Apr 2024 08:25:50 +0200 Subject: [PATCH 16/16] Fix compilation errors in tests --- tendermint/src/abci/event.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tendermint/src/abci/event.rs b/tendermint/src/abci/event.rs index 92aef5edb..aafb66c27 100644 --- a/tendermint/src/abci/event.rs +++ b/tendermint/src/abci/event.rs @@ -590,15 +590,15 @@ mod tests { let a = event .attributes .iter() - .find(|attr| attr.key == "a") + .find(|attr| attr.key_bytes() == b"a") .ok_or(()) - .and_then(|attr| serde_json::from_str(&attr.value).map_err(|_| ()))?; + .and_then(|attr| serde_json::from_slice(attr.value_bytes()).map_err(|_| ()))?; let b = event .attributes .iter() - .find(|attr| attr.key == "b") + .find(|attr| attr.key_bytes() == b"b") .ok_or(()) - .and_then(|attr| serde_json::from_str(&attr.value).map_err(|_| ()))?; + .and_then(|attr| serde_json::from_slice(attr.value_bytes()).map_err(|_| ()))?; Ok(MyEvent { a, b }) }