11use std:: {
22 cmp:: Ordering ,
33 io:: { Error , ErrorKind , Result } ,
4- sync:: Arc ,
54} ;
65
76use avalanche_types:: {
87 choices:: status:: Status ,
98 ids:: { must_deserialize_id, Id } ,
9+ rpcchainvm,
1010} ;
1111use avalanche_utils:: rfc3339;
1212use chrono:: { DateTime , NaiveDateTime , Utc } ;
1313use hmac_sha256:: Hash ;
1414use serde:: { Deserialize , Serialize } ;
15- use tokio:: sync:: RwLock ;
1615
17- use crate :: kvvm:: ChainVmInterior ;
16+ use crate :: kvvm:: ChainVm ;
1817
1918pub const DATA_LEN : usize = 32 ;
2019
20+ impl Block {
21+ pub fn new (
22+ parent : Id ,
23+ height : u64 ,
24+ data : Vec < u8 > ,
25+ timestamp : DateTime < Utc > ,
26+ status : Status ,
27+ ) -> Self {
28+ Self {
29+ parent,
30+ height,
31+ timestamp,
32+ data,
33+ status,
34+ id : Id :: empty ( ) ,
35+ bytes : Vec :: default ( ) ,
36+ vm : None ,
37+ }
38+ }
39+ }
40+
41+ pub trait MiniKvvmBlock : rpcchainvm:: concensus:: snowman:: Block + Serialize {
42+ fn data ( & self ) -> & [ u8 ] ;
43+ fn initialize ( & mut self , vm : ChainVm ) -> Result < Id > ;
44+ fn set_status ( & mut self , status : Status ) ;
45+ }
46+
2147// TODO remove
2248// Default is only used as a placeholder for unimplemented block logic
2349impl Default for Block {
2450 fn default ( ) -> Self {
2551 Self {
26- id : Some ( Id :: empty ( ) ) ,
52+ id : Id :: empty ( ) ,
2753 parent : Id :: empty ( ) ,
2854 timestamp : DateTime :: < Utc > :: from_utc ( NaiveDateTime :: from_timestamp ( 0 , 0 ) , Utc ) ,
2955 bytes : Vec :: default ( ) ,
3056 height : 0 ,
3157 status : Status :: Unknown ( "" . to_string ( ) ) ,
3258 data : Vec :: default ( ) ,
59+ vm : None ,
3360 }
3461 }
3562}
3663
3764/// snow/consensus/snowman/Block
3865/// ref. https://pkg.go.dev/github.com/ava-labs/avalanchego/snow/consensus/snowman#Block
39- #[ derive( Serialize , Debug , Clone , Deserialize ) ]
66+ #[ derive( Serialize , Clone , Deserialize ) ]
4067pub struct Block {
4168 #[ serde( deserialize_with = "must_deserialize_id" ) ]
4269 pub parent : Id ,
@@ -48,65 +75,120 @@ pub struct Block {
4875
4976 // generated not serialized
5077 #[ serde( skip) ]
51- id : Option < Id > ,
78+ id : Id ,
5279 // generated not serialized
5380 #[ serde( skip) ]
5481 bytes : Vec < u8 > ,
82+ #[ serde( skip) ]
83+ vm : Option < ChainVm > ,
5584}
5685
57- impl Block {
58- pub fn new (
59- parent : Id ,
60- height : u64 ,
61- data : Vec < u8 > ,
62- timestamp : DateTime < Utc > ,
63- status : Status ,
64- ) -> Result < Self > {
65- Ok ( Self {
66- parent,
67- height,
68- timestamp,
69- data,
70- status,
71- id : None ,
72- bytes : Vec :: default ( ) ,
73- } )
86+ #[ tonic:: async_trait]
87+ impl rpcchainvm:: concensus:: snowman:: Decidable for Block {
88+ /// id returns the ID of this block
89+ async fn id ( & self ) -> Id {
90+ self . id
7491 }
7592
76- pub fn parent ( & self ) -> Id {
77- self . parent
93+ /// status returns the status of this block
94+ async fn status ( & self ) -> Status {
95+ self . status . clone ( )
7896 }
7997
80- /// id returns the ID of this block
81- pub fn id ( & self ) -> Option < Id > {
82- self . id
98+ /// Accepts this element.
99+ async fn accept ( & mut self ) -> Result < ( ) > {
100+ let vm = self . vm . clone ( ) ;
101+ let vm = vm. ok_or ( Error :: new ( ErrorKind :: Other , "no vm associated with block" ) ) ?;
102+ let mut inner = vm. inner . write ( ) . await ;
103+
104+ self . status = Status :: Accepted ;
105+
106+ // add newly accepted block to state
107+ inner
108+ . state
109+ . put_block ( self . clone ( ) , vm. clone ( ) )
110+ . await
111+ . map_err ( |e| Error :: new ( ErrorKind :: Other , format ! ( "failed to put block: {:?}" , e) ) ) ?;
112+
113+ // set last accepted block to this block id
114+ inner
115+ . state
116+ . set_last_accepted_block_id ( & self . id )
117+ . await
118+ . map_err ( |e| Error :: new ( ErrorKind :: Other , format ! ( "failed to put block: {:?}" , e) ) ) ?;
119+
120+ // remove from verified blocks
121+ inner. verified_blocks . remove ( & self . id ) ;
122+ Ok ( ( ) )
123+ }
124+
125+ /// Rejects this element.
126+ async fn reject ( & mut self ) -> Result < ( ) > {
127+ let vm = self . vm . clone ( ) ;
128+ let vm = vm. ok_or ( Error :: new ( ErrorKind :: Other , "no vm associated with block" ) ) ?;
129+ let mut inner = vm. inner . write ( ) . await ;
130+
131+ self . status = Status :: Rejected ;
132+
133+ // add newly rejected block to state
134+ inner
135+ . state
136+ . put_block ( self . clone ( ) , vm. clone ( ) )
137+ . await
138+ . map_err ( |e| Error :: new ( ErrorKind :: Other , format ! ( "failed to put block: {:?}" , e) ) ) ?;
139+
140+ // remove from verified, as it is rejected
141+ inner. verified_blocks . remove ( & self . id ) ;
142+ Ok ( ( ) )
83143 }
144+ }
84145
85- pub fn timestamp ( & self ) -> & DateTime < Utc > {
86- & self . timestamp
146+ #[ tonic:: async_trait]
147+ impl rpcchainvm:: concensus:: snowman:: Block for Block {
148+ /// bytes returns the binary representation of this block
149+ async fn bytes ( & self ) -> & [ u8 ] {
150+ & self . bytes
151+ }
152+
153+ /// height returns this block's height. The genesis block has height 0.
154+ async fn height ( & self ) -> u64 {
155+ self . height
156+ }
157+
158+ async fn timestamp ( & self ) -> u64 {
159+ self . timestamp . timestamp ( ) as u64
160+ }
161+
162+ async fn parent ( & self ) -> Id {
163+ self . parent
87164 }
88165
89166 /// verify ensures that the state of the block is expected.
90- pub async fn verify ( & self , inner : & Arc < RwLock < ChainVmInterior > > ) -> Result < ( ) > {
91- let vm = inner. read ( ) . await ;
167+ async fn verify ( & self ) -> Result < ( ) > {
168+ let vm = self
169+ . vm
170+ . clone ( )
171+ . ok_or ( Error :: new ( ErrorKind :: Other , "no reference to vm" ) ) ?;
172+
173+ let vm = vm. inner . read ( ) . await ;
92174
93175 match vm. state . get_block ( self . parent ) . await ? {
94176 Some ( parent_block) => {
95177 // Ensure block height comes right after its parent's height
96- if parent_block. height ( ) + 1 != self . height ( ) {
178+ if parent_block. height ( ) . await + 1 != self . height {
97179 return Err ( Error :: new (
98180 ErrorKind :: InvalidData ,
99181 "failed to verify block invalid height" ,
100182 ) ) ;
101183 }
102184 // Ensure block timestamp is after its parent's timestamp.
103- if self . timestamp ( ) . cmp ( parent_block. timestamp ( ) ) == Ordering :: Less {
185+ if self . timestamp ( ) . await . cmp ( & parent_block. timestamp ( ) . await ) == Ordering :: Less {
104186 return Err ( Error :: new (
105187 ErrorKind :: InvalidData ,
106188 format ! (
107189 "block timestamp: {} is after parents: {}" ,
108- self . timestamp( ) ,
109- parent_block. timestamp( )
190+ self . timestamp( ) . await ,
191+ parent_block. timestamp( ) . await
110192 ) ,
111193 ) ) ;
112194 }
@@ -118,46 +200,38 @@ impl Block {
118200 ) ) ,
119201 }
120202 }
203+ }
121204
205+ impl MiniKvvmBlock for Block {
122206 /// data returns the block payload.
123- pub fn data ( & self ) -> & [ u8 ] {
207+ fn data ( & self ) -> & [ u8 ] {
124208 & self . data
125209 }
126210
127- /// bytes returns the binary representation of this block
128- pub fn bytes ( & self ) -> & [ u8 ] {
129- & self . bytes
130- }
131-
132- /// height returns this block's height. The genesis block has height 0.
133- pub fn height ( & self ) -> u64 {
134- self . height
135- }
136-
137- /// status returns the status of this block
138- pub fn status ( & self ) -> Status {
139- self . status . clone ( )
211+ fn set_status ( & mut self , status : Status ) {
212+ self . status = status;
140213 }
141214
142215 /// initialize populates the generated fields (id, bytes) of the the block and
143216 /// returns the generated id.
144- pub fn initialize ( & mut self ) -> Result < Id > {
145- if self . id . is_none ( ) {
217+ fn initialize ( & mut self , vm : ChainVm ) -> Result < Id > {
218+ if self . id . is_empty ( ) {
146219 match serde_json:: to_vec ( & self ) {
147220 // Populate generated fields
148221 Ok ( block_bytes) => {
149222 let block_data = block_bytes. as_slice ( ) ;
150223 let block_id = to_block_id ( & block_data) ;
151- self . id = Some ( block_id) ;
224+ self . id = block_id;
152225 self . bytes = block_bytes;
153- return Ok ( self . id . unwrap ( ) ) ;
226+ self . vm = Some ( vm) ;
227+ return Ok ( self . id ) ;
154228 }
155229 Err ( error) => {
156230 return Err ( Error :: new ( ErrorKind :: NotFound , error) ) ;
157231 }
158232 }
159233 }
160- Ok ( self . id . unwrap ( ) )
234+ Ok ( self . id )
161235 }
162236}
163237
@@ -169,10 +243,11 @@ fn new_id(bytes: [u8; DATA_LEN]) -> Id {
169243 Id :: from_slice ( & bytes)
170244}
171245
172- #[ test]
173- fn test_serialization_round_trip ( ) {
246+ #[ tokio:: test]
247+ async fn test_serialization_round_trip ( ) {
248+ use rpcchainvm:: concensus:: snowman:: Block as _; //Bring the block trait into scope for [.parent()]
174249 let block = Block :: default ( ) ;
175250 let writer = serde_json:: to_vec ( & block) . unwrap ( ) ;
176251 let value: Block = serde_json:: from_slice ( & writer) . unwrap ( ) ;
177- assert_eq ! ( block. parent( ) , value. parent( ) ) ;
252+ assert_eq ! ( block. parent( ) . await , value. parent( ) . await ) ;
178253}
0 commit comments