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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the snarkVM library.

// The snarkVM library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// The snarkVM library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with the snarkVM library. If not, see <https://www.gnu.org/licenses/>.

mod entry;
pub use entry::Entry;

mod helpers;
pub use helpers::{Balance, Owner};

mod bytes;
mod decrypt;
mod encrypt;
mod equal;
mod find;
mod is_owner;
mod num_randomizers;
mod parse_ciphertext;
mod parse_plaintext;
mod serial_number;
mod serialize;
mod tag;
mod to_bits;
mod to_commitment;
mod to_fields;

use crate::{Ciphertext, Identifier, Literal, Plaintext, ProgramID};
use snarkvm_console_account::{Address, PrivateKey, ViewKey};
use snarkvm_console_network::prelude::*;
use snarkvm_console_types::{Boolean, Field, Group, Scalar, U64};

use indexmap::IndexMap;

/// A value stored in program record.
#[derive(Clone)]
pub struct Record<N: Network, Private: Visibility> {
    /// The owner of the program record.
    owner: Owner<N, Private>,
    /// The Aleo balance (in gates) of the program record.
    gates: Balance<N, Private>,
    /// The program data.
    data: IndexMap<Identifier<N>, Entry<N, Private>>,
    /// The nonce of the program record.
    nonce: Group<N>,
}

impl<N: Network, Private: Visibility> Record<N, Private> {
    /// Initializes a new record plaintext.
    pub fn from_plaintext(
        owner: Owner<N, Plaintext<N>>,
        gates: Balance<N, Plaintext<N>>,
        data: IndexMap<Identifier<N>, Entry<N, Plaintext<N>>>,
        nonce: Group<N>,
    ) -> Result<Record<N, Plaintext<N>>> {
        let reserved = [Identifier::from_str("owner")?, Identifier::from_str("gates")?];
        // Ensure the members has no duplicate names.
        ensure!(!has_duplicates(data.keys().chain(reserved.iter())), "Found a duplicate entry name in a record");
        // Ensure the number of structs is within `N::MAX_DATA_ENTRIES`.
        ensure!(data.len() <= N::MAX_DATA_ENTRIES, "Found a record that exceeds size ({})", data.len());
        // Return the record.
        Ok(Record { owner, gates, data, nonce })
    }

    /// Initializes a new record ciphertext.
    pub fn from_ciphertext(
        owner: Owner<N, Ciphertext<N>>,
        gates: Balance<N, Ciphertext<N>>,
        data: IndexMap<Identifier<N>, Entry<N, Ciphertext<N>>>,
        nonce: Group<N>,
    ) -> Result<Record<N, Ciphertext<N>>> {
        let reserved = [Identifier::from_str("owner")?, Identifier::from_str("gates")?];
        // Ensure the members has no duplicate names.
        ensure!(!has_duplicates(data.keys().chain(reserved.iter())), "Found a duplicate entry name in a record");
        // Ensure the number of structs is within `N::MAX_DATA_ENTRIES`.
        ensure!(data.len() <= N::MAX_DATA_ENTRIES, "Found a record that exceeds size ({})", data.len());
        // Return the record.
        Ok(Record { owner, gates, data, nonce })
    }
}

impl<N: Network, Private: Visibility> Record<N, Private> {
    /// Returns the owner of the program record.
    pub const fn owner(&self) -> &Owner<N, Private> {
        &self.owner
    }

    /// Returns the gates of the program record.
    pub const fn gates(&self) -> &Balance<N, Private> {
        &self.gates
    }

    /// Returns the program data.
    pub const fn data(&self) -> &IndexMap<Identifier<N>, Entry<N, Private>> {
        &self.data
    }

    /// Returns the nonce of the program record.
    pub const fn nonce(&self) -> &Group<N> {
        &self.nonce
    }
}

impl<N: Network, Private: Visibility> Record<N, Private> {
    /// Returns the owner of the program record, and consumes `self`.
    pub fn into_owner(self) -> Owner<N, Private> {
        self.owner
    }

    /// Returns the gates of the program record, and consumes `self`.
    pub fn into_gates(self) -> Balance<N, Private> {
        self.gates
    }

    /// Returns the program data, and consumes `self`.
    pub fn into_data(self) -> IndexMap<Identifier<N>, Entry<N, Private>> {
        self.data
    }

    /// Returns the nonce of the program record, and consumes `self`.
    pub fn into_nonce(self) -> Group<N> {
        self.nonce
    }
}