Coverage Report

Created: 2024-05-16 12:16

/__w/smoldot/smoldot/repo/lib/src/transactions/validate/tests.rs
Line
Count
Source (jump to first uncovered line)
1
// Smoldot
2
// Copyright (C) 2023  Pierre Krieger
3
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
4
5
// This program is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
9
10
// This program is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
// GNU General Public License for more details.
14
15
// You should have received a copy of the GNU General Public License
16
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18
#![cfg(test)]
19
20
use crate::{
21
    executor::{self, runtime_call},
22
    header,
23
    trie::proof_decode,
24
};
25
use core::iter;
26
27
#[test]
28
1
fn validate_from_proof() {
29
1
    // Regression test for <https://github.com/smol-dot/smoldot/issues/873>.
30
1
31
1
    let test: Test = serde_json::from_str(include_str!("./test-fixture.json")).unwrap();
32
1
33
1
    let runtime = executor::host::HostVmPrototype::new(executor::host::Config {
34
1
        module: hex::decode(&test.runtime_code).unwrap(),
35
1
        heap_pages: executor::DEFAULT_HEAP_PAGES,
36
1
        allow_unresolved_imports: true,
37
1
        exec_hint: executor::vm::ExecHint::ExecuteOnceWithNonDeterministicValidation,
38
1
    })
39
1
    .unwrap();
40
1
41
1
    let call_proof = proof_decode::decode_and_verify_proof(proof_decode::Config {
42
1
        proof: hex::decode(&test.call_proof).unwrap(),
43
1
    })
44
1
    .unwrap();
45
1
46
1
    let scale_encoded_header = hex::decode(test.block_header).unwrap();
47
1
48
1
    let main_trie_root = header::decode(&scale_encoded_header, 4).unwrap().state_root;
49
1
50
1
    let mut validation_in_progress = runtime_call::run(runtime_call::Config {
51
1
        virtual_machine: runtime,
52
1
        function_to_call: super::VALIDATION_FUNCTION_NAME,
53
1
        parameter: super::validate_transaction_runtime_parameters_v3(
54
1
            iter::once(&hex::decode(test.transaction_bytes).unwrap()),
55
1
            super::TransactionSource::External,
56
1
            &header::hash_from_scale_encoded_header(&scale_encoded_header),
57
1
        ),
58
1
        storage_proof_size_behavior:
59
1
            runtime_call::StorageProofSizeBehavior::proof_recording_disabled(),
60
1
        storage_main_trie_changes: Default::default(),
61
1
        max_log_level: 0,
62
1
        calculate_trie_changes: false,
63
1
    })
64
1
    .unwrap();
65
66
    loop {
67
1
        match validation_in_progress {
68
1
            runtime_call::RuntimeCall::Finished(Ok(_)) => return, // Success,
69
0
            runtime_call::RuntimeCall::Finished(Err(_)) => panic!(),
70
15
            runtime_call::RuntimeCall::StorageGet(get) => {
71
15
                let value = call_proof
72
15
                    .storage_value(main_trie_root, get.key().as_ref())
73
15
                    .unwrap();
74
15
                validation_in_progress =
75
15
                    get.inject_value(value.map(|(val, ver)| 
(iter::once(val), ver)14
));
76
15
            }
77
0
            runtime_call::RuntimeCall::NextKey(nk) => {
78
0
                let next_key = call_proof
79
0
                    .next_key(
80
0
                        main_trie_root,
81
0
                        nk.key(),
82
0
                        nk.or_equal(),
83
0
                        nk.prefix(),
84
0
                        nk.branch_nodes(),
85
0
                    )
86
0
                    .unwrap();
87
0
                validation_in_progress = nk.inject_key(next_key);
88
0
            }
89
0
            runtime_call::RuntimeCall::ClosestDescendantMerkleValue(mv) => {
90
0
                let value = call_proof
91
0
                    .closest_descendant_merkle_value(main_trie_root, mv.key())
92
0
                    .unwrap();
93
0
                validation_in_progress = mv.inject_merkle_value(value);
94
0
            }
95
1
            runtime_call::RuntimeCall::SignatureVerification(r) => {
96
1
                validation_in_progress = r.verify_and_resume()
97
            }
98
0
            runtime_call::RuntimeCall::LogEmit(r) => validation_in_progress = r.resume(),
99
0
            runtime_call::RuntimeCall::OffchainStorageSet(r) => validation_in_progress = r.resume(),
100
0
            runtime_call::RuntimeCall::Offchain(_) => panic!(),
101
        }
102
    }
103
1
}
104
105
// Serde structs used to decode the test fixtures.
106
107
9
#[derive(
s5
erde::Deserialize)]
_RINvXs_NvXNvNtNtNtCsN16ciHI6Qf_7smoldot12transactions8validate5tests1__NtBa_4TestNtNtCsf0yC2YK6bpM_5serde2de11Deserialize11deserializeNtB5_7___FieldB1h_11deserializeINtNtCscu7pqq74Vb8_10serde_json2de6MapKeyNtNtB2I_4read7StrReadEEBg_
Line
Count
Source
107
4
#[derive(serde::Deserialize)]
Unexecuted instantiation: _RINvXs0_NvXNvNtNtNtCsN16ciHI6Qf_7smoldot12transactions8validate5tests1__NtBb_4TestNtNtCsf0yC2YK6bpM_5serde2de11Deserialize11deserializeNtB6_9___VisitorNtB1k_7Visitor9visit_seqINtNtCscu7pqq74Vb8_10serde_json2de9SeqAccessNtNtB2S_4read7StrReadEEBh_
_RINvXs0_NvXNvNtNtNtCsN16ciHI6Qf_7smoldot12transactions8validate5tests1__NtBb_4TestNtNtCsf0yC2YK6bpM_5serde2de11Deserialize11deserializeNtB6_9___VisitorNtB1k_7Visitor9visit_mapINtNtCscu7pqq74Vb8_10serde_json2de9MapAccessNtNtB2S_4read7StrReadEEBh_
Line
Count
Source
107
5
#[derive(
s1
erde::Deserialize)]
_RINvXNvXNvNtNtNtCsN16ciHI6Qf_7smoldot12transactions8validate5tests1__NtB8_4TestNtNtCsf0yC2YK6bpM_5serde2de11Deserialize11deserializeNtB3_14___FieldVisitorNtB1h_7Visitor9visit_strNtNtCscu7pqq74Vb8_10serde_json5error5ErrorEBe_
Line
Count
Source
107
4
#[derive(serde::Deserialize)]
Unexecuted instantiation: _RNvXs0_NvXNvNtNtNtCsN16ciHI6Qf_7smoldot12transactions8validate5tests1__NtBa_4TestNtNtCsf0yC2YK6bpM_5serde2de11Deserialize11deserializeNtB5_9___VisitorNtB1j_7Visitor9expecting
Unexecuted instantiation: _RNvXNvXNvNtNtNtCsN16ciHI6Qf_7smoldot12transactions8validate5tests1__NtB7_4TestNtNtCsf0yC2YK6bpM_5serde2de11Deserialize11deserializeNtB2_14___FieldVisitorNtB1g_7Visitor9expecting
Unexecuted instantiation: _RINvXNvXNvNtNtNtCsN16ciHI6Qf_7smoldot12transactions8validate5tests1__NtB8_4TestNtNtCsf0yC2YK6bpM_5serde2de11Deserialize11deserializeNtB3_14___FieldVisitorNtB1h_7Visitor9visit_u64pEBe_
Unexecuted instantiation: _RINvXNvXNvNtNtNtCsN16ciHI6Qf_7smoldot12transactions8validate5tests1__NtB8_4TestNtNtCsf0yC2YK6bpM_5serde2de11Deserialize11deserializeNtB3_14___FieldVisitorNtB1h_7Visitor11visit_bytespEBe_
108
struct Test {
109
    #[serde(rename = "transactionBytes")]
110
    transaction_bytes: String,
111
    #[serde(rename = "runtimeCode")]
112
    runtime_code: String,
113
    #[serde(rename = "callProof")]
114
    call_proof: String,
115
    #[serde(rename = "blockHeader")]
116
    block_header: String,
117
}