rpcpool / yellowstone-grpc

solana geyser grpc service
GNU Affero General Public License v3.0
246 stars 103 forks source link

Add non-streaming methods #112

Open linuskendall opened 1 year ago

linuskendall commented 1 year ago

I would like to add non streaming methods that could help users who are writing trading code:

Harder ones that we could potentially do if we add much more logic to the code

Ones that I don't know if possible (what info would we require to do this? maybe some modification to geyser interface to send some of this info on start up):

Others..?

linuskendall commented 1 year ago

See also #47, which can be a first version (not sure if it can include the solana validator version?).

shuimuliang commented 1 year ago

https://docs.solana.com/api/http#getlatestblockhash https://docs.solana.com/api/http#getblockheight https://docs.solana.com/api/http#getslot

shuimuliang commented 1 year ago

linuskendall: for getLatestBlockhash if we can we should use the existing interface I think via block notification + slot notification

shuimuliang commented 1 year ago

share read/write design for MessageBlockMeta

// plugin.rs
#[derive(Debug)]
pub struct PluginInner {
    // ...
    latest_block_meta: Arc<RwLock<Option<MessageBlockMeta>>>,
}

// grpc.rs
#[derive(Clone)]
pub struct GrpcService {
    // ...
    latest_block_meta: Arc<RwLock<Option<MessageBlockMeta>>>,
}

// plugin.rs
    fn notify_block_metadata(
        &mut self,
        blockinfo: ReplicaBlockInfoVersions<'_>,
    ) -> PluginResult<()> {
                // ...
               if let Ok(mut latest_block_meta_write_guard) = inner.latest_block_meta.write() {
                *latest_block_meta_write_guard = Some(block_meta.clone());
            }
}

// grpc.rs
    async fn get_latest_blockhash(&self, _request: Request<GetLatestBlockhashRequest>) -> Result<Response<GetLatestBlockhashResponse>, Status> {
        if let Ok(message_block_meta) = self.latest_block_meta.read() {
            let v= message_block_meta.as_ref();
            if let Some(v) = v {
                let response = GetLatestBlockhashResponse {
                    slot: v.slot,
                    blockhash: v.blockhash.clone(),
                    block_height: v.block_height.unwrap(),
                };
                return Ok(Response::new(response));
            }
        }

        Err(Status::internal("latest_block_meta is None"))
    }
shuimuliang commented 1 year ago

one more question for isBlockhashValid/is_blockhash_valid:

in Solana validator, we could hold a ArcBank instance, and query blockhash within the Bank

We could use the following method:

  1. at server startup, embed a RocksDB or third-party KV database.
  2. record newly received blockhash.
  3. if client queries, return the result.

The potential issue here is:

only newly added blockhashes are recorded at startup, and historical blockhashes are not recorded. it may be necessary to maintain a separate historical database for querying.