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
//! CPI wrapper for Alea's `verify` instruction.
//!
//! Consumer programs should call [`verify`] instead of invoking the raw
//! Anchor-generated `alea_verifier::cpi::verify` directly — this helper
//! captures the return data in the same expression, preventing the ordering
//! footgun described below.
//!
//! # CRITICAL: Return data ordering
//!
//! Solana's return data is single-slot — each CPI call that sets return data
//! overwrites the previous value. Consumer programs MUST read the randomness
//! into a local variable immediately after this call, BEFORE making any other
//! CPI calls (token transfers, system program, etc.):
//!
//! ```rust,ignore
//! // CORRECT — capture first, then downstream CPIs are safe
//! let randomness = alea_sdk::cpi::verify(/* args */)?.into_inner();
//! token::transfer(transfer_ctx, amount)?;
//!
//! // WRONG — token::transfer overwrites Alea's return data
//! token::transfer(transfer_ctx, amount)?;
//! let randomness = alea_sdk::cpi::verify(/* args */)?.into_inner(); // stale/empty
//! ```
use *;
/// Captured drand randomness from a successful [`verify`] CPI.
///
/// Wraps the raw `[u8; 32]` randomness in a `#[must_use]` newtype. This
/// closes a class of consumer bugs that `?` extraction on a bare
/// `Result<[u8; 32]>` cannot catch: writing
/// `alea_sdk::cpi::verify(...)?;` discards the randomness silently with
/// no compiler warning, because `?` extracts the `Ok` variant and Rust
/// happily drops array return values.
///
/// By wrapping in a `#[must_use]` struct, `alea_sdk::cpi::verify(...)?;`
/// produces a compile-time `unused_must_use` warning — the consumer is
/// forced to capture the result. Phase 4.5 T1-17 integration-audit fix.
///
/// # Usage
///
/// ```rust,ignore
/// // Preferred — capture the bytes:
/// let randomness = alea_sdk::cpi::verify(/* … */)?.into_inner();
///
/// // Or keep the wrapper and read without moving:
/// let verified = alea_sdk::cpi::verify(/* … */)?;
/// let first_u64 = u64::from_le_bytes(
/// verified.as_bytes()[0..8].try_into().unwrap()
/// );
/// ```
;
/// Verify a drand beacon via CPI to Alea and receive 32 bytes of randomness.
///
/// Pattern A (auto-deserialize) per ADR 0030. Anchor 0.30.x's generated
/// `alea_verifier::cpi::verify(...)` returns `Result<Return<[u8; 32]>>`;
/// `.get()` unwraps to the deserialized `[u8; 32]` directly. No
/// `get_return_data()` call is required.
///
/// Returns a [`VerifiedRandomness`] wrapper (must_use) rather than a bare
/// `[u8; 32]` so that `alea_sdk::cpi::verify(...)?;` without binding
/// produces a compile warning instead of silently dropping the bytes.
/// Call `.into_inner()` or `.as_bytes()` to reach the raw randomness.
///
/// # Arguments
/// * `alea_program` — the Alea program (must be `ALEAydzHd…` per
/// [`crate::PROGRAM_ID`])
/// * `config` — the Alea Config PDA (must be checked in the consumer's
/// Accounts struct with `seeds::program = alea_program.key()` — see
/// the `lib.rs` doc example and ADR 0034)
/// * `payer` — signer, passed through to Alea's Verify accounts struct
/// * `round` — drand round number
/// * `signature` — 64-byte G1 point (uncompressed, x || y big-endian)
///
/// # Errors
/// Returns Alea's on-chain error codes (6000–6012) for signature,
/// chain-hash, or field-arithmetic failures. See [`crate::AleaError`].