Line data Source code
1 : #include "fd_failover_proto.h"
2 :
3 : #include "../../ballet/ed25519/fd_ed25519.h"
4 : #include "../../ballet/sha256/fd_sha256.h"
5 : #include "../../disco/keyguard/fd_keyguard.h"
6 :
7 : FD_STATIC_ASSERT( sizeof(FD_KEYGUARD_FAILOVER_CLIENT_DOMAIN)-1UL==FD_KEYGUARD_FAILOVER_DOMAIN_SZ, client_proof_domain );
8 : FD_STATIC_ASSERT( sizeof(FD_KEYGUARD_FAILOVER_SERVER_DOMAIN)-1UL==FD_KEYGUARD_FAILOVER_DOMAIN_SZ, server_proof_domain );
9 :
10 : int
11 : fd_failover_hello_check( fd_failover_hello_t const * self,
12 54 : fd_failover_hello_t const * peer ) {
13 54 : if( FD_UNLIKELY( self->version!=peer->version ) ) return FD_FAILOVER_HELLO_ERR_VERSION;
14 54 : if( FD_UNLIKELY( self->holds>1 || peer->holds>1 ) ) return FD_FAILOVER_HELLO_ERR_HOLDS;
15 54 : if( FD_UNLIKELY( self->mode!=FD_FAILOVER_MODE_ALPENGLOW ||
16 54 : self->mode!=peer->mode ) ) return FD_FAILOVER_HELLO_ERR_MODE;
17 36 : if( FD_UNLIKELY( !self->boot_id || !peer->boot_id ) ) return FD_FAILOVER_HELLO_ERR_BOOT_ID;
18 36 : if( FD_UNLIKELY( !fd_memeq( self->staked_pubkey, peer->staked_pubkey, 32UL ) ) ) return FD_FAILOVER_HELLO_ERR_STAKED;
19 27 : if( FD_UNLIKELY( self->boot_id==peer->boot_id ) ) return FD_FAILOVER_HELLO_ERR_SELF;
20 24 : if( FD_UNLIKELY( self->holds && peer->holds ) ) return FD_FAILOVER_HELLO_ERR_BOTH_HOLD;
21 21 : return FD_FAILOVER_HELLO_OK;
22 24 : }
23 :
24 : void
25 : fd_failover_admission_hash( fd_failover_admission_start_t const * start,
26 : uchar const * client_hello,
27 : fd_failover_admission_challenge_t const * challenge,
28 6 : uchar out[ 32 ] ) {
29 6 : fd_sha256_t sha[1];
30 6 : fd_sha256_init( sha );
31 6 : fd_sha256_append( sha, start, sizeof(*start) );
32 6 : fd_sha256_append( sha, client_hello, start->client_hello_sz );
33 6 : fd_sha256_append( sha, challenge, sizeof(*challenge) );
34 6 : fd_sha256_fini( sha, out );
35 6 : }
36 :
37 : void
38 : fd_failover_response_hash( uchar const transcript[ 32 ],
39 : uchar const client_proof[ 64 ],
40 : uchar const * server_flight,
41 : ushort server_flight_sz,
42 6 : uchar out[ 32 ] ) {
43 6 : fd_sha256_t sha[1];
44 6 : fd_sha256_init( sha );
45 6 : fd_sha256_append( sha, transcript, 32UL );
46 6 : fd_sha256_append( sha, client_proof, 64UL );
47 6 : fd_sha256_append( sha, &server_flight_sz, sizeof(server_flight_sz) );
48 6 : fd_sha256_append( sha, server_flight, server_flight_sz );
49 6 : fd_sha256_fini( sha, out );
50 6 : }
51 :
52 : void
53 : fd_failover_proof_msg( uchar out[ FD_KEYGUARD_FAILOVER_PROOF_SZ ],
54 : int server,
55 12 : uchar const transcript[ 32 ] ) {
56 12 : fd_memcpy( out, server ? FD_KEYGUARD_FAILOVER_SERVER_DOMAIN : FD_KEYGUARD_FAILOVER_CLIENT_DOMAIN,
57 12 : FD_KEYGUARD_FAILOVER_DOMAIN_SZ );
58 12 : fd_memcpy( out+FD_KEYGUARD_FAILOVER_DOMAIN_SZ, transcript, 32UL );
59 12 : }
60 :
61 : int
62 : fd_failover_handoff_request_decode( fd_failover_handoff_request_t * out,
63 : uchar const * payload,
64 90 : ulong payload_sz ) {
65 90 : if( FD_UNLIKELY( payload_sz!=sizeof(fd_failover_handoff_request_t) ) ) return 0;
66 87 : fd_failover_handoff_request_t request;
67 87 : fd_memcpy( &request, payload, sizeof(request) );
68 87 : if( FD_UNLIKELY( !request.handoff_id || !request.target_boot_id ) ) return 0;
69 84 : *out = request;
70 84 : return 1;
71 87 : }
72 :
73 : int
74 : fd_failover_handoff_result_decode( fd_failover_handoff_result_t * out,
75 : uchar const * payload,
76 24 : ulong payload_sz ) {
77 24 : if( FD_UNLIKELY( payload_sz!=sizeof(fd_failover_handoff_result_t) ) ) return 0;
78 21 : fd_failover_handoff_result_t result;
79 21 : fd_memcpy( &result, payload, sizeof(result) );
80 21 : if( FD_UNLIKELY( !result.handoff_id ) ) return 0;
81 18 : *out = result;
82 18 : return 1;
83 21 : }
84 :
85 : ulong
86 : fd_failover_demoted_encode( uchar * out,
87 : ulong handoff_id,
88 : ulong target_boot_id,
89 : ulong last_vote_slot,
90 : uchar const * state,
91 42 : ulong state_sz ) {
92 42 : if( FD_UNLIKELY( !state_sz || state_sz>FD_FAILOVER_ALPENGLOW_STATE_MAX ) ) return 0UL;
93 :
94 42 : fd_failover_demoted_t demoted = {
95 42 : .handoff_id = handoff_id,
96 42 : .target_boot_id = target_boot_id,
97 42 : .last_vote_slot = last_vote_slot,
98 42 : .mode = (uchar)FD_FAILOVER_MODE_ALPENGLOW,
99 42 : .state_len = (ushort)state_sz,
100 42 : };
101 42 : fd_memcpy( out, &demoted, sizeof(demoted) );
102 42 : fd_memcpy( out+sizeof(demoted), state, state_sz );
103 42 : return sizeof(demoted)+state_sz;
104 42 : }
105 :
106 : int
107 : fd_failover_demoted_decode( fd_failover_demoted_t * out,
108 : uchar const * payload,
109 39 : ulong payload_sz ) {
110 39 : if( FD_UNLIKELY( payload_sz<sizeof(fd_failover_demoted_t) ||
111 39 : payload_sz>FD_FAILOVER_DEMOTED_PAYLOAD_MAX ) ) return 0;
112 :
113 39 : fd_failover_demoted_t demoted;
114 39 : fd_memcpy( &demoted, payload, sizeof(demoted) );
115 :
116 39 : ulong state_sz = payload_sz-sizeof(fd_failover_demoted_t);
117 39 : if( FD_UNLIKELY( (ulong)demoted.state_len!=state_sz ||
118 39 : !state_sz || state_sz>FD_FAILOVER_ALPENGLOW_STATE_MAX ||
119 39 : demoted.mode!=(uchar)FD_FAILOVER_MODE_ALPENGLOW ||
120 39 : demoted.last_vote_slot==FD_FAILOVER_SLOT_NULL ) ) return 0;
121 :
122 30 : *out = demoted;
123 30 : return 1;
124 39 : }
125 :
126 : ulong
127 : fd_failover_promote_ack_encode( uchar * out,
128 15 : ulong handoff_id ) {
129 15 : fd_failover_promote_ack_t ack = { .handoff_id=handoff_id };
130 15 : fd_memcpy( out, &ack, sizeof(ack) );
131 15 : return sizeof(ack);
132 15 : }
133 :
134 : ulong
135 : fd_failover_promote_rejected_encode( uchar * out,
136 : ulong handoff_id,
137 6 : uchar reason ) {
138 6 : if( FD_UNLIKELY( reason==(uchar)FD_FAILOVER_REJECT_NONE || reason>=(uchar)FD_FAILOVER_REJECT_CNT ) ) return 0UL;
139 6 : fd_failover_promote_rejected_t rej = { .handoff_id=handoff_id, .reason=reason };
140 6 : fd_memcpy( out, &rej, sizeof(rej) );
141 6 : return sizeof(rej);
142 6 : }
143 :
144 : int
145 : fd_failover_promote_ack_decode( fd_failover_promote_ack_t * out,
146 : uchar const * payload,
147 12 : ulong payload_sz ) {
148 12 : if( FD_UNLIKELY( payload_sz!=sizeof(fd_failover_promote_ack_t) ) ) return 0;
149 12 : fd_memcpy( out, payload, sizeof(fd_failover_promote_ack_t) );
150 12 : return 1;
151 12 : }
152 :
153 : int
154 : fd_failover_promote_rejected_decode( fd_failover_promote_rejected_t * out,
155 : uchar const * payload,
156 3 : ulong payload_sz ) {
157 3 : if( FD_UNLIKELY( payload_sz!=sizeof(fd_failover_promote_rejected_t) ) ) return 0;
158 3 : fd_failover_promote_rejected_t rej;
159 3 : fd_memcpy( &rej, payload, sizeof(rej) );
160 3 : if( FD_UNLIKELY( rej.reason==(uchar)FD_FAILOVER_REJECT_NONE || rej.reason>=(uchar)FD_FAILOVER_REJECT_CNT ) ) return 0;
161 3 : *out = rej;
162 3 : return 1;
163 3 : }
|