@@ -70,7 +70,7 @@ use crate::http::{decode_http_body, decode_http_request};
70
70
use crate :: stacks_common:: types:: PublicKey ;
71
71
use crate :: {
72
72
BlockProposal , EventError , MessageSlotID as MessageSlotIDTrait ,
73
- SignerMessage as SignerMessageTrait ,
73
+ SignerMessage as SignerMessageTrait , VERSION_STRING ,
74
74
} ;
75
75
76
76
define_u8_enum ! (
@@ -615,15 +615,15 @@ impl std::fmt::Display for BlockResponse {
615
615
BlockResponse :: Accepted ( a) => {
616
616
write ! (
617
617
f,
618
- "BlockAccepted: signer_sighash = {}, signature = {}" ,
619
- a. signer_signature_hash, a. signature
618
+ "BlockAccepted: signer_sighash = {}, signature = {}, version = {} " ,
619
+ a. signer_signature_hash, a. signature, a . metadata . server_version
620
620
)
621
621
}
622
622
BlockResponse :: Rejected ( r) => {
623
623
write ! (
624
624
f,
625
- "BlockRejected: signer_sighash = {}, code = {}, reason = {}, signature = {}" ,
626
- r. reason_code, r. reason, r. signer_signature_hash, r. signature
625
+ "BlockRejected: signer_sighash = {}, code = {}, reason = {}, signature = {}, version = {} " ,
626
+ r. reason_code, r. reason, r. signer_signature_hash, r. signature, r . metadata . server_version
627
627
)
628
628
}
629
629
}
@@ -636,6 +636,7 @@ impl BlockResponse {
636
636
Self :: Accepted ( BlockAccepted {
637
637
signer_signature_hash : hash,
638
638
signature : sig,
639
+ metadata : SignerMessageMetadata :: default ( ) ,
639
640
} )
640
641
}
641
642
@@ -681,32 +682,99 @@ impl StacksMessageCodec for BlockResponse {
681
682
}
682
683
}
683
684
685
+ /// Metadata for signer messages
686
+ #[ derive( Clone , Debug , PartialEq , Serialize , Deserialize ) ]
687
+ pub struct SignerMessageMetadata {
688
+ /// The signer's server version
689
+ pub server_version : String ,
690
+ }
691
+
692
+ /// To ensure backwards compatibility, when deserializing,
693
+ /// if no bytes are found, return empty metadata
694
+ impl StacksMessageCodec for SignerMessageMetadata {
695
+ fn consensus_serialize < W : Write > ( & self , fd : & mut W ) -> Result < ( ) , CodecError > {
696
+ write_next ( fd, & self . server_version . as_bytes ( ) . to_vec ( ) ) ?;
697
+ Ok ( ( ) )
698
+ }
699
+
700
+ fn consensus_deserialize < R : Read > ( fd : & mut R ) -> Result < Self , CodecError > {
701
+ match read_next :: < Vec < u8 > , _ > ( fd) {
702
+ Ok ( server_version) => {
703
+ let server_version = String :: from_utf8 ( server_version) . map_err ( |e| {
704
+ CodecError :: DeserializeError ( format ! (
705
+ "Failed to decode server version: {:?}" ,
706
+ & e
707
+ ) )
708
+ } ) ?;
709
+ Ok ( Self { server_version } )
710
+ }
711
+ Err ( _) => {
712
+ // For backwards compatibility, return empty metadata
713
+ Ok ( Self :: empty ( ) )
714
+ }
715
+ }
716
+ }
717
+ }
718
+
719
+ impl Default for SignerMessageMetadata {
720
+ fn default ( ) -> Self {
721
+ Self {
722
+ server_version : VERSION_STRING . to_string ( ) ,
723
+ }
724
+ }
725
+ }
726
+
727
+ impl SignerMessageMetadata {
728
+ /// Empty metadata
729
+ pub fn empty ( ) -> Self {
730
+ Self {
731
+ server_version : String :: new ( ) ,
732
+ }
733
+ }
734
+ }
735
+
684
736
/// A rejection response from a signer for a proposed block
685
737
#[ derive( Clone , Debug , PartialEq , Serialize , Deserialize ) ]
686
738
pub struct BlockAccepted {
687
739
/// The signer signature hash of the block that was accepted
688
740
pub signer_signature_hash : Sha512Trunc256Sum ,
689
741
/// The signer's signature across the acceptance
690
742
pub signature : MessageSignature ,
743
+ /// Signer message metadata
744
+ pub metadata : SignerMessageMetadata ,
691
745
}
692
746
693
747
impl StacksMessageCodec for BlockAccepted {
694
748
fn consensus_serialize < W : Write > ( & self , fd : & mut W ) -> Result < ( ) , CodecError > {
695
749
write_next ( fd, & self . signer_signature_hash ) ?;
696
750
write_next ( fd, & self . signature ) ?;
751
+ write_next ( fd, & self . metadata ) ?;
697
752
Ok ( ( ) )
698
753
}
699
754
700
755
fn consensus_deserialize < R : Read > ( fd : & mut R ) -> Result < Self , CodecError > {
701
756
let signer_signature_hash = read_next :: < Sha512Trunc256Sum , _ > ( fd) ?;
702
757
let signature = read_next :: < MessageSignature , _ > ( fd) ?;
758
+ let metadata = read_next :: < SignerMessageMetadata , _ > ( fd) ?;
703
759
Ok ( Self {
704
760
signer_signature_hash,
705
761
signature,
762
+ metadata,
706
763
} )
707
764
}
708
765
}
709
766
767
+ impl BlockAccepted {
768
+ /// Create a new BlockAccepted for the provided block signer signature hash and signature
769
+ pub fn new ( signer_signature_hash : Sha512Trunc256Sum , signature : MessageSignature ) -> Self {
770
+ Self {
771
+ signer_signature_hash,
772
+ signature,
773
+ metadata : SignerMessageMetadata :: default ( ) ,
774
+ }
775
+ }
776
+ }
777
+
710
778
/// A rejection response from a signer for a proposed block
711
779
#[ derive( Clone , Debug , PartialEq , Serialize , Deserialize ) ]
712
780
pub struct BlockRejection {
@@ -720,6 +788,8 @@ pub struct BlockRejection {
720
788
pub signature : MessageSignature ,
721
789
/// The chain id
722
790
pub chain_id : u32 ,
791
+ /// Signer message metadata
792
+ pub metadata : SignerMessageMetadata ,
723
793
}
724
794
725
795
impl BlockRejection {
@@ -741,6 +811,7 @@ impl BlockRejection {
741
811
signer_signature_hash,
742
812
signature : MessageSignature :: empty ( ) ,
743
813
chain_id,
814
+ metadata : SignerMessageMetadata :: default ( ) ,
744
815
} ;
745
816
rejection
746
817
. sign ( private_key)
@@ -765,6 +836,7 @@ impl BlockRejection {
765
836
signer_signature_hash : reject. signer_signature_hash ,
766
837
chain_id,
767
838
signature : MessageSignature :: empty ( ) ,
839
+ metadata : SignerMessageMetadata :: default ( ) ,
768
840
} ;
769
841
rejection
770
842
. sign ( private_key)
@@ -814,6 +886,7 @@ impl StacksMessageCodec for BlockRejection {
814
886
write_next ( fd, & self . signer_signature_hash ) ?;
815
887
write_next ( fd, & self . chain_id ) ?;
816
888
write_next ( fd, & self . signature ) ?;
889
+ write_next ( fd, & self . metadata ) ?;
817
890
Ok ( ( ) )
818
891
}
819
892
@@ -826,12 +899,14 @@ impl StacksMessageCodec for BlockRejection {
826
899
let signer_signature_hash = read_next :: < Sha512Trunc256Sum , _ > ( fd) ?;
827
900
let chain_id = read_next :: < u32 , _ > ( fd) ?;
828
901
let signature = read_next :: < MessageSignature , _ > ( fd) ?;
902
+ let metadata = read_next :: < SignerMessageMetadata , _ > ( fd) ?;
829
903
Ok ( Self {
830
904
reason,
831
905
reason_code,
832
906
signer_signature_hash,
833
907
chain_id,
834
908
signature,
909
+ metadata,
835
910
} )
836
911
}
837
912
}
@@ -988,6 +1063,7 @@ mod test {
988
1063
let accepted = BlockAccepted {
989
1064
signer_signature_hash : Sha512Trunc256Sum ( [ 0u8 ; 32 ] ) ,
990
1065
signature : MessageSignature :: empty ( ) ,
1066
+ metadata : SignerMessageMetadata :: default ( ) ,
991
1067
} ;
992
1068
let response = BlockResponse :: Accepted ( accepted) ;
993
1069
let serialized_response = response. serialize_to_vec ( ) ;
@@ -1012,6 +1088,7 @@ mod test {
1012
1088
let accepted = BlockAccepted {
1013
1089
signer_signature_hash : Sha512Trunc256Sum ( [ 2u8 ; 32 ] ) ,
1014
1090
signature : MessageSignature :: empty ( ) ,
1091
+ metadata : SignerMessageMetadata :: default ( ) ,
1015
1092
} ;
1016
1093
let signer_message = SignerMessage :: BlockResponse ( BlockResponse :: Accepted ( accepted) ) ;
1017
1094
let serialized_signer_message = signer_message. serialize_to_vec ( ) ;
@@ -1178,6 +1255,55 @@ mod test {
1178
1255
169 , 171 , 178 , 41 , 98 , 13 , 216 , 224 , 242 , 37 , 214 , 52 , 1 , 227 , 108 , 100 , 129 ,
1179
1256
127 , 178 , 158 , 108 , 5 , 89 , 29 , 203 , 233 , 92 , 81 , 45 , 243 ,
1180
1257
] ) ,
1258
+ metadata: SignerMessageMetadata :: empty( ) ,
1259
+ } ) )
1260
+ ) ;
1261
+
1262
+ assert_eq ! (
1263
+ block_accepted,
1264
+ SignerMessage :: BlockResponse ( BlockResponse :: Accepted ( BlockAccepted {
1265
+ signer_signature_hash: Sha512Trunc256Sum ( [
1266
+ 17 , 113 , 113 , 73 , 103 , 124 , 42 , 201 , 125 , 21 , 174 , 89 , 84 , 247 , 167 , 22 , 241 ,
1267
+ 1 , 0 , 185 , 203 , 129 , 162 , 191 , 39 , 85 , 27 , 47 , 46 , 84 , 239 , 25
1268
+ ] ) ,
1269
+ metadata: SignerMessageMetadata :: empty( ) ,
1270
+ signature: MessageSignature ( [
1271
+ 0 , 28 , 105 , 79 , 129 , 52 , 197 , 201 , 15 , 47 , 43 , 205 , 51 , 14 , 159 , 66 , 50 , 4 ,
1272
+ 136 , 79 , 0 , 27 , 93 , 240 , 5 , 15 , 54 , 162 , 196 , 255 , 121 , 221 , 147 , 82 , 43 , 178 ,
1273
+ 174 , 57 , 94 , 168 , 125 , 228 , 150 , 72 , 134 , 68 , 117 , 7 , 193 , 131 , 116 , 183 , 164 ,
1274
+ 110 , 226 , 227 , 113 , 233 , 191 , 51 , 47 , 7 , 6 , 163 , 232
1275
+ ] ) ,
1276
+ } ) )
1277
+ ) ;
1278
+ }
1279
+
1280
+ #[ test]
1281
+ fn test_block_response_metadata ( ) {
1282
+ let block_rejected_hex = "010100000050426c6f636b206973206e6f7420612074656e7572652d737461727420626c6f636b2c20616e642068617320616e20756e7265636f676e697a65642074656e75726520636f6e73656e7375732068617368000691f95f84b7045f7dce7757052caa986ef042cb58f7df5031a3b5b5d0e3dda63e80000000006fb349212e1a1af1a3c712878d5159b5ec14636adb6f70be00a6da4ad4f88a9934d8a9abb229620dd8e0f225d63401e36c64817fb29e6c05591dcbe95c512df30000000b48656c6c6f20776f726c64" ;
1283
+ let block_rejected_bytes = hex_bytes ( & block_rejected_hex) . unwrap ( ) ;
1284
+ let block_accepted_hex = "010011717149677c2ac97d15ae5954f7a716f10100b9cb81a2bf27551b2f2e54ef19001c694f8134c5c90f2f2bcd330e9f423204884f001b5df0050f36a2c4ff79dd93522bb2ae395ea87de4964886447507c18374b7a46ee2e371e9bf332f0706a3e80000000b48656c6c6f20776f726c64" ;
1285
+ let block_accepted_bytes = hex_bytes ( & block_accepted_hex) . unwrap ( ) ;
1286
+ let block_rejected = read_next :: < SignerMessage , _ > ( & mut & block_rejected_bytes[ ..] )
1287
+ . expect ( "Failed to deserialize BlockRejection" ) ;
1288
+ let block_accepted = read_next :: < SignerMessage , _ > ( & mut & block_accepted_bytes[ ..] )
1289
+ . expect ( "Failed to deserialize BlockRejection" ) ;
1290
+
1291
+ assert_eq ! (
1292
+ block_rejected,
1293
+ SignerMessage :: BlockResponse ( BlockResponse :: Rejected ( BlockRejection {
1294
+ reason_code: RejectCode :: ValidationFailed ( ValidateRejectCode :: NoSuchTenure ) ,
1295
+ reason: "Block is not a tenure-start block, and has an unrecognized tenure consensus hash" . to_string( ) ,
1296
+ signer_signature_hash: Sha512Trunc256Sum ( [ 145 , 249 , 95 , 132 , 183 , 4 , 95 , 125 , 206 , 119 , 87 , 5 , 44 , 170 , 152 , 110 , 240 , 66 , 203 , 88 , 247 , 223 , 80 , 49 , 163 , 181 , 181 , 208 , 227 , 221 , 166 , 62 ] ) ,
1297
+ chain_id: CHAIN_ID_TESTNET ,
1298
+ signature: MessageSignature ( [
1299
+ 0 , 111 , 179 , 73 , 33 , 46 , 26 , 26 , 241 , 163 , 199 , 18 , 135 , 141 , 81 , 89 , 181 , 236 ,
1300
+ 20 , 99 , 106 , 219 , 111 , 112 , 190 , 0 , 166 , 218 , 74 , 212 , 248 , 138 , 153 , 52 , 216 ,
1301
+ 169 , 171 , 178 , 41 , 98 , 13 , 216 , 224 , 242 , 37 , 214 , 52 , 1 , 227 , 108 , 100 , 129 ,
1302
+ 127 , 178 , 158 , 108 , 5 , 89 , 29 , 203 , 233 , 92 , 81 , 45 , 243 ,
1303
+ ] ) ,
1304
+ metadata: SignerMessageMetadata {
1305
+ server_version: "Hello world" . to_string( ) ,
1306
+ } ,
1181
1307
} ) )
1182
1308
) ;
1183
1309
@@ -1188,6 +1314,9 @@ mod test {
1188
1314
17 , 113 , 113 , 73 , 103 , 124 , 42 , 201 , 125 , 21 , 174 , 89 , 84 , 247 , 167 , 22 , 241 ,
1189
1315
1 , 0 , 185 , 203 , 129 , 162 , 191 , 39 , 85 , 27 , 47 , 46 , 84 , 239 , 25
1190
1316
] ) ,
1317
+ metadata: SignerMessageMetadata {
1318
+ server_version: "Hello world" . to_string( ) ,
1319
+ } ,
1191
1320
signature: MessageSignature ( [
1192
1321
0 , 28 , 105 , 79 , 129 , 52 , 197 , 201 , 15 , 47 , 43 , 205 , 51 , 14 , 159 , 66 , 50 , 4 ,
1193
1322
136 , 79 , 0 , 27 , 93 , 240 , 5 , 15 , 54 , 162 , 196 , 255 , 121 , 221 , 147 , 82 , 43 , 178 ,
@@ -1197,4 +1326,13 @@ mod test {
1197
1326
} ) )
1198
1327
) ;
1199
1328
}
1329
+
1330
+ #[ test]
1331
+ fn test_empty_metadata ( ) {
1332
+ let serialized_metadata = [ 0u8 ; 0 ] ;
1333
+ let deserialized_metadata =
1334
+ read_next :: < SignerMessageMetadata , _ > ( & mut & serialized_metadata[ ..] )
1335
+ . expect ( "Failed to deserialize SignerMessageMetadata" ) ;
1336
+ assert_eq ! ( deserialized_metadata, SignerMessageMetadata :: empty( ) ) ;
1337
+ }
1200
1338
}
0 commit comments