@@ -6,7 +6,7 @@ use std::{
6
6
} ;
7
7
8
8
use avalanche_types:: {
9
- choices:: status,
9
+ choices:: status:: { self , Status } ,
10
10
ids,
11
11
rpcchainvm:: {
12
12
self ,
@@ -18,12 +18,16 @@ use semver::Version;
18
18
use tokio:: sync:: { mpsc:: Sender , RwLock } ;
19
19
20
20
use crate :: {
21
+ api,
21
22
block:: Block as StatefulBlock ,
22
23
block:: { self , state:: State } ,
23
24
chain:: { self , tx:: Transaction } ,
24
25
genesis:: Genesis ,
25
26
} ;
26
27
28
+ const PUBLIC_API_ENDPOINT : & str = "/public" ;
29
+ const VERSION : & str = env ! ( "CARGO_PKG_VERSION" ) ;
30
+
27
31
pub struct ChainVmInterior {
28
32
pub ctx : Option < rpcchainvm:: context:: Context > ,
29
33
pub bootstrapped : bool ,
@@ -176,27 +180,20 @@ impl rpcchainvm::common::apphandler::AppHandler for ChainVm {
176
180
#[ tonic:: async_trait]
177
181
impl rpcchainvm:: common:: vm:: Connector for ChainVm {
178
182
async fn connected ( & self , _id : & ids:: node:: Id ) -> Result < ( ) > {
179
- Err ( Error :: new (
180
- ErrorKind :: Unsupported ,
181
- "connected not implemented" ,
182
- ) )
183
+ // no-op
184
+ Ok ( ( ) )
183
185
}
184
186
185
187
async fn disconnected ( & self , _id : & ids:: node:: Id ) -> Result < ( ) > {
186
- Err ( Error :: new (
187
- ErrorKind :: Unsupported ,
188
- "disconnected not implemented" ,
189
- ) )
188
+ // no-op
189
+ Ok ( ( ) )
190
190
}
191
191
}
192
192
193
193
#[ tonic:: async_trait]
194
194
impl rpcchainvm:: health:: Checkable for ChainVm {
195
195
async fn health_check ( & self ) -> Result < Vec < u8 > > {
196
- Err ( Error :: new (
197
- ErrorKind :: Unsupported ,
198
- "health check not implemented" ,
199
- ) )
196
+ Ok ( "200" . as_bytes ( ) . to_vec ( ) )
200
197
}
201
198
}
202
199
@@ -217,6 +214,10 @@ impl rpcchainvm::common::vm::Vm for ChainVm {
217
214
let mut vm = self . inner . write ( ) . await ;
218
215
vm. ctx = ctx;
219
216
217
+ let version =
218
+ Version :: parse ( VERSION ) . map_err ( |e| Error :: new ( ErrorKind :: Other , e. to_string ( ) ) ) ?;
219
+ vm. version = version;
220
+
220
221
let current = db_manager. current ( ) . await ?;
221
222
self . db = current. db . clone ( ) ;
222
223
@@ -282,44 +283,70 @@ impl rpcchainvm::common::vm::Vm for ChainVm {
282
283
283
284
/// Called when the node is shutting down.
284
285
async fn shutdown ( & self ) -> Result < ( ) > {
285
- Err ( Error :: new (
286
- ErrorKind :: Unsupported ,
287
- "shutdown not implemented" ,
288
- ) )
286
+ // grpc servers are shutdown via broadcast channel
287
+ // if additional shutdown is required we can extend.
288
+ Ok ( ( ) )
289
289
}
290
290
291
- /// Communicates to Vm the next state it starts.
292
- async fn set_state ( & self , _snow_state : rpcchainvm:: snow:: State ) -> Result < ( ) > {
293
- Err ( Error :: new (
294
- ErrorKind :: Unsupported ,
295
- "set_state not implemented" ,
296
- ) )
291
+ /// Communicates to Vm the next state phase.
292
+ async fn set_state ( & self , snow_state : rpcchainvm:: snow:: State ) -> Result < ( ) > {
293
+ let mut vm = self . inner . write ( ) . await ;
294
+ match snow_state. try_into ( ) {
295
+ // Initializing is called by chains manager when it is creating the chain.
296
+ Ok ( rpcchainvm:: snow:: State :: Initializing ) => {
297
+ log:: debug!( "set_state: initializing" ) ;
298
+ vm. bootstrapped = false ;
299
+ Ok ( ( ) )
300
+ }
301
+ Ok ( rpcchainvm:: snow:: State :: StateSyncing ) => {
302
+ log:: debug!( "set_state: state syncing" ) ;
303
+ Err ( Error :: new ( ErrorKind :: Other , "state sync is not supported" ) )
304
+ }
305
+ // Bootstrapping is called by the bootstrapper to signal bootstrapping has started.
306
+ Ok ( rpcchainvm:: snow:: State :: Bootstrapping ) => {
307
+ log:: debug!( "set_state: bootstrapping" ) ;
308
+ vm. bootstrapped = false ;
309
+ Ok ( ( ) )
310
+ }
311
+ // NormalOp os called when consensus has started signalling bootstrap phase is complete.
312
+ Ok ( rpcchainvm:: snow:: State :: NormalOp ) => {
313
+ log:: debug!( "set_state: normal op" ) ;
314
+ vm. bootstrapped = true ;
315
+ Ok ( ( ) )
316
+ }
317
+ Err ( _) => Err ( Error :: new ( ErrorKind :: Other , "unknown state" ) ) ,
318
+ }
297
319
}
298
320
299
321
/// Returns the version of the VM this node is running.
300
322
async fn version ( & self ) -> Result < String > {
301
- Err ( Error :: new (
302
- ErrorKind :: Unsupported ,
303
- "version not implemented" ,
304
- ) )
323
+ Ok ( String :: from ( VERSION ) )
305
324
}
306
325
307
- /// Creates the HTTP handlers for custom Vm network calls.
326
+ /// Creates the HTTP handlers for custom Vm network calls
327
+ /// for "ext/vm/[vmId]"
308
328
async fn create_static_handlers (
309
329
& self ,
310
330
) -> std:: io:: Result <
311
- std:: collections:: HashMap <
312
- String ,
313
- avalanche_types:: rpcchainvm:: common:: http_handler:: HttpHandler ,
314
- > ,
331
+ std:: collections:: HashMap < String , rpcchainvm:: common:: http_handler:: HttpHandler > ,
315
332
> {
316
- Err ( Error :: new (
317
- ErrorKind :: Unsupported ,
318
- "create_static_handlers not implemented" ,
319
- ) )
333
+ log:: debug!( "create_static_handlers called" ) ;
334
+
335
+ // Initialize the jsonrpc public service and handler
336
+ let service = api:: service:: Service :: new ( self . clone ( ) ) ;
337
+ let mut handler = jsonrpc_core:: IoHandler :: new ( ) ;
338
+ handler. extend_with ( api:: Service :: to_delegate ( service) ) ;
339
+
340
+ let http_handler = rpcchainvm:: common:: http_handler:: HttpHandler :: new_from_u8 ( 0 , handler)
341
+ . map_err ( |_| Error :: from ( ErrorKind :: InvalidData ) ) ?;
342
+
343
+ let mut handlers = HashMap :: new ( ) ;
344
+ handlers. insert ( String :: from ( PUBLIC_API_ENDPOINT ) , http_handler) ;
345
+ Ok ( handlers)
320
346
}
321
347
322
- /// Creates the HTTP handlers for custom chain network calls.
348
+ /// Creates the HTTP handlers for custom chain network calls
349
+ /// for "ext/vm/[chainId]"
323
350
async fn create_handlers (
324
351
& self ,
325
352
) -> std:: io:: Result <
@@ -328,10 +355,7 @@ impl rpcchainvm::common::vm::Vm for ChainVm {
328
355
avalanche_types:: rpcchainvm:: common:: http_handler:: HttpHandler ,
329
356
> ,
330
357
> {
331
- Err ( Error :: new (
332
- ErrorKind :: Unsupported ,
333
- "create_handlers not implemented" ,
334
- ) )
358
+ Ok ( HashMap :: new ( ) )
335
359
}
336
360
}
337
361
@@ -340,12 +364,16 @@ impl rpcchainvm::snowman::block::Getter for ChainVm {
340
364
/// Attempt to load a block.
341
365
async fn get_block (
342
366
& self ,
343
- _id : ids:: Id ,
367
+ id : ids:: Id ,
344
368
) -> Result < Box < dyn rpcchainvm:: concensus:: snowman:: Block + Send + Sync > > {
345
- Err ( Error :: new (
346
- ErrorKind :: Unsupported ,
347
- "get_block not implemented" ,
348
- ) )
369
+ let mut vm = self . inner . write ( ) . await ;
370
+
371
+ let block =
372
+ vm. state . get_block ( id) . await . map_err ( |e| {
373
+ Error :: new ( ErrorKind :: Other , format ! ( "failed to get block: {:?}" , e) )
374
+ } ) ?;
375
+
376
+ Ok ( Box :: new ( block) )
349
377
}
350
378
}
351
379
@@ -354,12 +382,25 @@ impl rpcchainvm::snowman::block::Parser for ChainVm {
354
382
/// Attempt to create a block from a stream of bytes.
355
383
async fn parse_block (
356
384
& self ,
357
- _bytes : & [ u8 ] ,
385
+ bytes : & [ u8 ] ,
358
386
) -> Result < Box < dyn rpcchainvm:: concensus:: snowman:: Block + Send + Sync > > {
359
- Err ( Error :: new (
360
- ErrorKind :: Unsupported ,
361
- "parse_block not implemented" ,
362
- ) )
387
+ let mut vm = self . inner . write ( ) . await ;
388
+
389
+ let new_block = vm
390
+ . state
391
+ . parse_block ( bytes. to_vec ( ) , Status :: Processing )
392
+ . await
393
+ . map_err ( |e| Error :: new ( ErrorKind :: Other , format ! ( "failed to parse block: {:?}" , e) ) ) ?;
394
+
395
+ log:: debug!( "parsed block id: {}" , new_block. id) ;
396
+
397
+ match vm. state . get_block ( new_block. id ) . await {
398
+ Ok ( old_block) => {
399
+ log:: debug!( "returning previously parsed block id: {}" , old_block. id) ;
400
+ return Ok ( Box :: new ( old_block) ) ;
401
+ }
402
+ Err ( _) => return Ok ( Box :: new ( new_block) ) ,
403
+ } ;
363
404
}
364
405
}
365
406
@@ -429,19 +470,20 @@ impl rpcchainvm::snowman::block::ChainVm for ChainVm {
429
470
}
430
471
431
472
/// Notify the Vm of the currently preferred block.
432
- async fn set_preference ( & self , _id : ids:: Id ) -> Result < ( ) > {
433
- Err ( Error :: new (
434
- ErrorKind :: Unsupported ,
435
- "set_preference not implemented" ,
436
- ) )
473
+ async fn set_preference ( & self , id : ids:: Id ) -> Result < ( ) > {
474
+ let mut vm = self . inner . write ( ) . await ;
475
+ vm . preferred_block_id = Some ( id ) ;
476
+
477
+ Ok ( ( ) )
437
478
}
438
479
439
480
// Returns the Id of the last accepted block.
440
481
async fn last_accepted ( & self ) -> Result < ids:: Id > {
441
- Err ( Error :: new (
442
- ErrorKind :: Unsupported ,
443
- "last_accepted not implemented" ,
444
- ) )
482
+ let vm = self . inner . write ( ) . await ;
483
+ let state = vm. state . clone ( ) ;
484
+ let last_accepted_id = state. get_last_accepted ( ) . await ?;
485
+
486
+ Ok ( last_accepted_id)
445
487
}
446
488
447
489
/// Attempts to issue a transaction into consensus.
0 commit comments