sui_light_client/
package_store.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

use anyhow::Result;
use async_trait::async_trait;
use move_core_types::account_address::AccountAddress;
use std::collections::HashMap;
use std::sync::Arc;
use sui_package_resolver::{error::Error as PackageResolverError, Package, PackageStore};
use tokio::sync::Mutex;
use tracing::{error, info};

use crate::config::Config;
use crate::verifier::get_verified_object;

pub struct RemotePackageStore {
    config: Config,
    cache: Mutex<HashMap<AccountAddress, Arc<Package>>>,
}

impl RemotePackageStore {
    pub fn new(config: Config) -> Self {
        Self {
            config,
            cache: Mutex::new(HashMap::new()),
        }
    }
}

#[async_trait]
impl PackageStore for RemotePackageStore {
    async fn fetch(&self, id: AccountAddress) -> sui_package_resolver::Result<Arc<Package>> {
        // Check if we have it in the cache
        let res: Result<Arc<Package>> = async move {
            if let Some(package) = self.cache.lock().await.get(&id) {
                info!("Fetch Package: {} cache hit", id);
                return Ok(package.clone());
            }

            info!("Fetch Package: {}", id);

            let object = get_verified_object(&self.config, id.into()).await?;
            let package = Arc::new(Package::read_from_object(&object)?);

            // Add to the cache
            self.cache.lock().await.insert(id, package.clone());

            Ok(package)
        }
        .await;
        res.map_err(|e| {
            error!("Fetch Package: {} error: {:?}", id, e);
            PackageResolverError::PackageNotFound(id)
        })
    }
}