safety_rules/
configurable_validator_signer.rs

1// Copyright (c) The Diem Core Contributors
2// SPDX-License-Identifier: Apache-2.0
3
4// Copyright 2021 Conflux Foundation. All rights reserved.
5// Conflux is free software and distributed under GNU General Public License.
6// See http://www.gnu.org/licenses/
7
8use serde::Serialize;
9
10use diem_crypto::hash::CryptoHash;
11use diem_global_constants::CONSENSUS_KEY;
12use diem_types::{
13    account_address::AccountAddress,
14    validator_config::{
15        ConsensusPrivateKey, ConsensusPublicKey, ConsensusSignature,
16        ConsensusVRFPrivateKey,
17    },
18    validator_signer::ValidatorSigner,
19};
20
21use crate::{Error, PersistentSafetyStorage};
22
23/// A ConfigurableValidatorSigner is a ValidatorSigner wrapper that offers
24/// either a ValidatorSigner instance or a ValidatorHandle instance, depending
25/// on the configuration chosen. This abstracts away the complexities of
26/// handling either instance, while offering the same API as a ValidatorSigner.
27pub enum ConfigurableValidatorSigner {
28    Signer(ValidatorSigner),
29    Handle(ValidatorHandle),
30}
31
32impl ConfigurableValidatorSigner {
33    /// Returns a new ValidatorSigner instance
34    pub fn new_signer(
35        author: AccountAddress, consensus_key: ConsensusPrivateKey,
36        vrf_private_key: Option<ConsensusVRFPrivateKey>,
37    ) -> Self {
38        let signer =
39            ValidatorSigner::new(author, consensus_key, vrf_private_key);
40        ConfigurableValidatorSigner::Signer(signer)
41    }
42
43    /// Returns a new ValidatorHandle instance
44    pub fn new_handle(
45        author: AccountAddress, key_version: ConsensusPublicKey,
46    ) -> Self {
47        let handle = ValidatorHandle::new(author, key_version);
48        ConfigurableValidatorSigner::Handle(handle)
49    }
50
51    /// Returns the author associated with the signer configuration.
52    pub fn author(&self) -> AccountAddress {
53        match self {
54            ConfigurableValidatorSigner::Signer(signer) => signer.author(),
55            ConfigurableValidatorSigner::Handle(handle) => handle.author(),
56        }
57    }
58
59    /// Returns the public key associated with the signer configuration.
60    pub fn public_key(&self) -> ConsensusPublicKey {
61        match self {
62            ConfigurableValidatorSigner::Signer(signer) => signer.public_key(),
63            ConfigurableValidatorSigner::Handle(handle) => handle.key_version(),
64        }
65    }
66
67    /// Signs a given message using the signer configuration.
68    pub fn sign<T: Serialize + CryptoHash>(
69        &self, message: &T, storage: &PersistentSafetyStorage,
70    ) -> Result<ConsensusSignature, Error> {
71        match self {
72            ConfigurableValidatorSigner::Signer(signer) => {
73                Ok(signer.sign(message))
74            }
75            ConfigurableValidatorSigner::Handle(handle) => {
76                handle.sign(message, storage)
77            }
78        }
79    }
80}
81
82/// A ValidatorHandle associates a validator with a consensus key version held
83/// in storage. In contrast to a ValidatorSigner, ValidatorHandle does not hold
84/// the private key directly but rather holds a reference to that private key
85/// which should be accessed using the handle and the secure storage backend.
86pub struct ValidatorHandle {
87    author: AccountAddress,
88    key_version: ConsensusPublicKey,
89}
90
91impl ValidatorHandle {
92    pub fn new(
93        author: AccountAddress, key_version: ConsensusPublicKey,
94    ) -> Self {
95        ValidatorHandle {
96            author,
97            key_version,
98        }
99    }
100
101    /// Returns the author associated with this handle.
102    pub fn author(&self) -> AccountAddress { self.author }
103
104    /// Returns the public key version associated with this handle.
105    pub fn key_version(&self) -> ConsensusPublicKey { self.key_version.clone() }
106
107    /// Signs a given message using this handle and a given secure storage
108    /// backend.
109    pub fn sign<T: Serialize + CryptoHash>(
110        &self, message: &T, storage: &PersistentSafetyStorage,
111    ) -> Result<ConsensusSignature, Error> {
112        storage.sign(CONSENSUS_KEY.into(), self.key_version(), message)
113    }
114}