Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/ballet/bls/Local.mk
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
$(call add-hdrs,fd_bls12_381.h fd_bls.h)
$(call add-hdrs,fd_bls12_381.h fd_bls.h fd_bls_err.h)
$(call add-objs,fd_bls12_381 fd_bls,fd_ballet)
$(call make-unit-test,test_bls12_381,test_bls12_381,fd_ballet fd_util,$(BLST_LIBS))
$(call run-unit-test,test_bls12_381)
50 changes: 42 additions & 8 deletions src/ballet/bls/fd_bls.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,18 @@ fd_bls_sec_derive( fd_bls_sec_t * sk,
}

void
fd_bls_sig_ser( uchar out[ static FD_BLS_SIG_SZ ],
fd_bls_sig_t const * sig ) {
fd_bls_sig_ser( fd_bls_sig_t const * sig,
uchar buf[ static FD_BLS_SIG_SZ ] ) {
blst_p2_affine a[1];
blst_p2_to_affine( a, sig );
blst_p2_affine_serialize( out, a );
blst_p2_affine_serialize( buf, a );
}

int
fd_bls_sig_de( fd_bls_sig_t * sig,
uchar const in[ static FD_BLS_SIG_SZ ] ) {
uchar const buf[ static FD_BLS_SIG_SZ ] ) {
blst_p2_affine a[1];
if( FD_UNLIKELY( blst_p2_deserialize( a, in )!=BLST_SUCCESS ) ) return -1;
if( FD_UNLIKELY( blst_p2_deserialize( a, buf )!=BLST_SUCCESS ) ) return -1;
if( FD_UNLIKELY( !blst_p2_affine_in_g2( a ) ) ) return -1;
blst_p2_from_affine( sig, a );
return 0;
Expand All @@ -65,14 +65,29 @@ pub_from_bytes( blst_p1_affine * out,

int
fd_bls_pub_de( fd_bls_pub_t * pub,
uchar const * in,
ulong in_sz ) {
uchar const * buf,
ulong buf_sz ) {
blst_p1_affine a[1];
if( FD_UNLIKELY( !pub_from_bytes( a, in, in_sz ) ) ) return -1;
if( FD_UNLIKELY( !pub_from_bytes( a, buf, buf_sz ) ) ) return -1;
blst_p1_from_affine( pub, a );
return 0;
}

fd_bls_agg_t *
fd_bls_agg_construct( fd_bls_agg_t * agg,
fd_bls_pub_t const * pub,
fd_bls_sig_t const * sig,
fd_bls_set_t const * set ) {
fd_bls_set_copy( agg->set, set );
for( ulong rank = fd_bls_set_const_iter_init( set );
!fd_bls_set_const_iter_done( rank );
rank = fd_bls_set_const_iter_next( set, rank ) ) {
blst_p1_add_or_double( &agg->pub, &agg->pub, pub+rank );
blst_p2_add_or_double( &agg->sig, &agg->sig, sig+rank );
}
return agg;
}

int
fd_bls_agg_verify( uchar const * msg,
ulong msg_sz,
Expand Down Expand Up @@ -146,3 +161,22 @@ fd_bls_agg_verify_bisect( fd_bls_agg_t const * agg,
}
return fd_bls_agg_verify_linear( &key, msg, msg_sz, pub, sig, bad );
}

int
fd_bls_agg_verify_subtract( fd_bls_agg_t * agg,
uchar const * msg,
ulong msg_sz,
fd_bls_pub_t const * pub,
fd_bls_sig_t const * sig,
fd_bls_set_t * bad ) {
if( FD_LIKELY( fd_bls_agg_verify( msg, msg_sz, &agg->pub, &agg->sig ) ) ) { fd_bls_set_null( bad ); return FD_BLS_SUCCESS; }
fd_bls_agg_verify_bisect( agg, msg, msg_sz, pub, sig, bad );
fd_bls_agg_t sub = { 0 };
fd_bls_agg_construct( &sub, pub, sig, bad );
blst_p1_cneg( &sub.pub, 1 ); blst_p1_add_or_double( &agg->pub, &agg->pub, &sub.pub );
blst_p2_cneg( &sub.sig, 1 ); blst_p2_add_or_double( &agg->sig, &agg->sig, &sub.sig );
fd_bls_set_subtract( agg->set, agg->set, bad );
if( FD_UNLIKELY( fd_bls_set_is_null( agg->set ) ) ) return FD_BLS_ERR_EMPTY;
if( FD_UNLIKELY( blst_p1_is_inf( &agg->pub ) ) ) return FD_BLS_ERR_INFINITY;
return FD_BLS_SUCCESS;
}
38 changes: 20 additions & 18 deletions src/ballet/bls/fd_bls.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "../../util/fd_util.h"
#include "../../third_party/blst/bindings/blst.h"
#include "fd_bls_err.h"

#define FD_BLS_SEC_SZ (32UL)
#define FD_BLS_PUB_SZ (96UL)
Expand Down Expand Up @@ -31,46 +32,39 @@ typedef struct fd_bls_agg fd_bls_agg_t;

FD_PROTOTYPES_BEGIN

/* SecretKey::to_pk */

void
fd_bls_sec_to_pub( fd_bls_sec_t const * sec,
fd_bls_pub_t * pub );

/* solana_bls_signatures::SecretKey::derive */

void
fd_bls_sec_derive( fd_bls_sec_t * sec,
uchar const * ikm,
ulong ikm_sz );

/* SecretKey::sign_bytes */

void
fd_bls_sec_sign( fd_bls_sec_t const * sec,
uchar const * msg,
ulong msg_sz,
fd_bls_sig_t * sig );

/* fd_bls_sig_ser writes the canonical uncompressed encoding of sig
(FD_BLS_SIG_SZ bytes) to out. fd_bls_sig_de parses such an encoding
into sig, returning 0 on success and -1 if the bytes are not a valid
G2 point. Translates between raw bytes and the canonical encoding. */

void
fd_bls_sig_ser( uchar out[ static FD_BLS_SIG_SZ ],
fd_bls_sig_t const * sig );
fd_bls_sig_ser( fd_bls_sig_t const * sig,
uchar buf[ static FD_BLS_SIG_SZ ] );

int
fd_bls_sig_de( fd_bls_sig_t * sig,
uchar const in[ static FD_BLS_SIG_SZ ] );

/* PublicKey::try_from_bytes */
uchar const buf[ static FD_BLS_SIG_SZ ] );

int
fd_bls_pub_de( fd_bls_pub_t * pub,
uchar const * in,
ulong in_sz );
uchar const * buf,
ulong buf_sz );

fd_bls_agg_t *
fd_bls_agg_construct( fd_bls_agg_t * agg,
fd_bls_pub_t const * pub,
fd_bls_sig_t const * sig,
fd_bls_set_t const * set );

int
fd_bls_agg_verify( uchar const * msg,
Expand All @@ -94,6 +88,14 @@ fd_bls_agg_verify_bisect( fd_bls_agg_t const * agg,
fd_bls_sig_t const * sig,
fd_bls_set_t * bad );

int
fd_bls_agg_verify_subtract( fd_bls_agg_t * agg,
uchar const * msg,
ulong msg_sz,
fd_bls_pub_t const * pub,
fd_bls_sig_t const * sig,
fd_bls_set_t * bad );

FD_PROTOTYPES_END

#endif
3 changes: 1 addition & 2 deletions src/ballet/bls/fd_bls12_381.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
#define HEADER_fd_src_ballet_bls_fd_bls12_381_h

#include "../fd_ballet_base.h"

#define FD_BLS_SUCCESS (0)
#include "fd_bls_err.h"

/* Max size for the pairing function */
#define FD_BLS12_381_PAIRING_BATCH_SZ (8UL)
Expand Down
8 changes: 8 additions & 0 deletions src/ballet/bls/fd_bls_err.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef HEADER_fd_src_ballet_bls_fd_bls_err_h
#define HEADER_fd_src_ballet_bls_fd_bls_err_h

#define FD_BLS_SUCCESS (0)
#define FD_BLS_ERR_EMPTY (-1)
#define FD_BLS_ERR_INFINITY (-2)

#endif /* HEADER_fd_src_ballet_bls_fd_bls_err_h */
19 changes: 10 additions & 9 deletions src/choreo/votor/ag_pool.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "ag_slot_state.h"
#include "ag_finality_tracker.h"
#include "ag_parent_ready_tracker.h"
#include "../../flamenco/alpenglow/fd_block_marker.h"

#define QUEUE_NAME pool_events
#define QUEUE_T ag_event_pool_t
Expand Down Expand Up @@ -105,7 +106,7 @@ ulong
ag_pool_footprint( ulong slot_max ) {
if( FD_UNLIKELY( slot_max<AG_SLOTS_PER_WINDOW ) ) return 0UL;

ulong slot_chain_cnt = slot_state_map_chain_cnt_est( slot_max );
ulong slot_chain_cnt = slot_state_map_chain_cnt_est( slot_max+FD_NUM_SLOTS_FOR_REWARD );
ulong s2n_max = slot_max*AG_EQVOC_BLOCK_HASH_MAX;
ulong s2n_chain_cnt = s2n_waiting_parent_cert_map_chain_cnt_est( s2n_max );

Expand All @@ -130,7 +131,7 @@ ag_pool_footprint( ulong slot_max ) {
FD_LAYOUT_INIT,
alignof(ag_pool_t), sizeof(ag_pool_t) ),
alignof(slot_states_t), sizeof(slot_states_t) ),
slot_state_pool_align(), slot_state_pool_footprint( slot_max ) ),
slot_state_pool_align(), slot_state_pool_footprint( slot_max+FD_NUM_SLOTS_FOR_REWARD ) ),
slot_state_map_align(), slot_state_map_footprint ( slot_chain_cnt ) ),
ag_parent_ready_tracker_align(), ag_parent_ready_tracker_footprint( slot_max ) ),
ag_finality_tracker_align(), ag_finality_tracker_footprint( slot_max ) ),
Expand Down Expand Up @@ -168,14 +169,14 @@ ag_pool_new( void * mem,
fd_memset( mem, 0, footprint );

ulong s2n_max = slot_max*AG_EQVOC_BLOCK_HASH_MAX;
ulong slot_chain_cnt = slot_state_map_chain_cnt_est( slot_max );
ulong slot_chain_cnt = slot_state_map_chain_cnt_est( slot_max+FD_NUM_SLOTS_FOR_REWARD );
ulong s2n_chain_cnt = s2n_waiting_parent_cert_map_chain_cnt_est( s2n_max );


FD_SCRATCH_ALLOC_INIT( l, mem );
ag_pool_t * pool = FD_SCRATCH_ALLOC_APPEND( l, alignof(ag_pool_t), sizeof(ag_pool_t) );
void * slot_states = FD_SCRATCH_ALLOC_APPEND( l, alignof(slot_states_t), sizeof(slot_states_t) );
void * slot_state_pool = FD_SCRATCH_ALLOC_APPEND( l, slot_state_pool_align(), slot_state_pool_footprint( slot_max ) );
void * slot_state_pool = FD_SCRATCH_ALLOC_APPEND( l, slot_state_pool_align(), slot_state_pool_footprint( slot_max+FD_NUM_SLOTS_FOR_REWARD ) );
void * slot_state_map = FD_SCRATCH_ALLOC_APPEND( l, slot_state_map_align(), slot_state_map_footprint ( slot_chain_cnt ) );
void * parent_ready_tracker = FD_SCRATCH_ALLOC_APPEND( l, ag_parent_ready_tracker_align(), ag_parent_ready_tracker_footprint( slot_max ) );
void * finality_tracker = FD_SCRATCH_ALLOC_APPEND( l, ag_finality_tracker_align(), ag_finality_tracker_footprint( slot_max ) );
Expand All @@ -200,7 +201,7 @@ ag_pool_new( void * mem,
pool->next_epoch_slot = ULONG_MAX;

pool->slot_states = (slot_states_t *)slot_states;
pool->slot_states->pool = slot_state_pool_join( slot_state_pool_new( slot_state_pool, slot_max ) );
pool->slot_states->pool = slot_state_pool_join( slot_state_pool_new( slot_state_pool, slot_max+FD_NUM_SLOTS_FOR_REWARD ) );
pool->slot_states->map = slot_state_map_join ( slot_state_map_new ( slot_state_map, slot_chain_cnt, seed ) );

pool->parent_ready_tracker = ag_parent_ready_tracker_join( ag_parent_ready_tracker_new( parent_ready_tracker, slot_max, seed ) );
Expand Down Expand Up @@ -277,7 +278,6 @@ ag_pool_strerror( int err ) {
case AG_POOL_ERR_DUPLICATE: return "duplicate vote or cert";
case AG_POOL_ERR_SLASHABLE: return "vote constitutes a slashable offence";
case AG_POOL_ERR_CERT_VERIFY: return "cert failed the signature or threshold check";
case AG_POOL_ERR_VOTE_VERIFY: return "vote(s) failed the signature check";
default: return "unknown";
}
}
Expand Down Expand Up @@ -314,7 +314,8 @@ handle_finalization( ag_pool_t * self,
pool_events_push( self->pool_events, event );
}
ulong first_unpruned_slot = ag_finality_tracker_first_unpruned_slot( self->finality_tracker );
for( ulong slot = self->parent_ready_tracker->root; slot<first_unpruned_slot; slot++ ) {
ulong retained_slot = fd_ulong_sat_sub( first_unpruned_slot, FD_NUM_SLOTS_FOR_REWARD );
for( ulong slot = fd_ulong_sat_sub( self->parent_ready_tracker->root, FD_NUM_SLOTS_FOR_REWARD ); slot<retained_slot; slot++ ) {
slot_state_ele_t * ele = slot_state_map_ele_remove( self->slot_states->map, &slot, NULL, self->slot_states->pool );
if( FD_LIKELY( ele ) ) slot_state_pool_ele_release( self->slot_states->pool, ele );
}
Expand Down Expand Up @@ -501,12 +502,12 @@ ag_pool_add_vote( ag_pool_t * self,
ag_event_cert_t cert_events [ AG_SLOT_STATE_OUT_CERT_MAX ]; ulong cert_event_cnt;
ag_event_pool_t pool_events [ AG_SLOT_STATE_OUT_EVENT_MAX ]; ulong pool_event_cnt;
ag_event_repair_t repair_events[ AG_SLOT_STATE_OUT_REPAIR_MAX ]; ulong repair_event_cnt;
int ok = ag_slot_state_add_vote( slot_state_, vote, voter_stake, cert_events, &cert_event_cnt, pool_events, &pool_event_cnt, repair_events, &repair_event_cnt, bad );
ag_slot_state_add_vote( slot_state_, vote, voter_stake, cert_events, &cert_event_cnt, pool_events, &pool_event_cnt, repair_events, &repair_event_cnt, bad );

for( ulong i=0UL; i<cert_event_cnt; i++ ) add_valid_cert( self, &cert_events[i].cert, bad );
for( ulong i=0UL; i<pool_event_cnt; i++ ) { pool_events [i].seq = self->seq++; pool_events_push ( self->pool_events, pool_events [i] ); }
for( ulong i=0UL; i<repair_event_cnt; i++ ) { repair_events[i].seq = self->seq++; repair_events_push( self->repair_events, repair_events[i] ); }
return ok ? AG_POOL_SUCCESS : AG_POOL_ERR_VOTE_VERIFY;
return AG_POOL_SUCCESS;
}

ag_slot_state_t const *
Expand Down
1 change: 0 additions & 1 deletion src/choreo/votor/ag_pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
#define AG_POOL_ERR_DUPLICATE (-2)
#define AG_POOL_ERR_SLASHABLE (-3)
#define AG_POOL_ERR_CERT_VERIFY (-4)
#define AG_POOL_ERR_VOTE_VERIFY (-5)

typedef struct ag_pool ag_pool_t;

Expand Down
18 changes: 14 additions & 4 deletions src/choreo/votor/ag_slot_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,10 @@ subtract_votes( ag_slot_state_t * self,
if( FD_UNLIKELY( kind==AG_VOTE_KIND_NOTAR ) ) {
voted_stake->top_notar = 0UL;
for( ulong i=0UL; i<voted_stake->notar_cnt; i++ ) {
voted_stake->top_notar = fd_ulong_max( voted_stake->top_notar, voted_stake->notar[i].stake ); /* FIXME slow */
if( FD_LIKELY( voted_stake->notar[i].stake>voted_stake->top_notar ) ) { /* FIXME slow */
voted_stake->top_notar = voted_stake->notar[i].stake;
memcpy( voted_stake->top_notar_hash, voted_stake->notar[i].hash, sizeof(ag_block_hash_t) );
}
}
}
return !emptied && !blst_p1_is_inf( &agg->pub );
Expand Down Expand Up @@ -308,7 +311,10 @@ count_notar_stake( ag_slot_state_t * self,

ulong notar_stake = voted_stake_for_hash->stake;
voted_stake->notar_or_skip += stake;
voted_stake->top_notar = fd_ulong_max( notar_stake, voted_stake->top_notar );
if( FD_LIKELY( notar_stake>voted_stake->top_notar ) ) {
voted_stake->top_notar = notar_stake;
memcpy( voted_stake->top_notar_hash, block_hash, sizeof(ag_block_hash_t) );
}

if( FD_UNLIKELY( !block_hash_set_contains( &self->sent_safe_to_notar, block_hash ) ) ) {
switch( check_safe_to_notar( self, block_hash, bad ) ) {
Expand All @@ -323,7 +329,9 @@ count_notar_stake( ag_slot_state_t * self,
default: break;
}
}
if( FD_UNLIKELY( check_safe_to_skip( self, bad ) ) ) out_pool_events[ (*out_pool_event_cnt)++ ] = (ag_event_pool_t){ .kind = AG_EVENT_POOL_SAFE_TO_SKIP, .safe_to_skip = slot };
if( FD_UNLIKELY( check_safe_to_skip( self, bad ) ) ) {
out_pool_events[ (*out_pool_event_cnt)++ ] = (ag_event_pool_t){ .kind = AG_EVENT_POOL_SAFE_TO_SKIP, .safe_to_skip = slot };
}
if( FD_UNLIKELY( !fd_bls_set_is_null( bad ) ) ) {
voted_stake_for_hash = NULL;
for( ulong i=0UL; i<voted_stake->notar_cnt; i++ ) {
Expand Down Expand Up @@ -490,7 +498,9 @@ count_skip_stake( ag_slot_state_t * self,
}
}

if( FD_UNLIKELY( check_safe_to_skip( self, bad ) ) ) out_pool_events[ (*out_pool_event_cnt)++ ] = (ag_event_pool_t){ .kind = AG_EVENT_POOL_SAFE_TO_SKIP, .safe_to_skip = slot };
if( FD_UNLIKELY( check_safe_to_skip( self, bad ) ) ) {
out_pool_events[ (*out_pool_event_cnt)++ ] = (ag_event_pool_t){ .kind = AG_EVENT_POOL_SAFE_TO_SKIP, .safe_to_skip = slot };
}
if( FD_UNLIKELY( !fd_bls_set_is_null( bad ) && !fd_bls_set_test( fallback ? voted_stake->skip_fallback_agg.set : voted_stake->skip_agg.set, rank ) ) ) return 0;

ulong total_skip_stake = voted_stake->skip + voted_stake->skip_fallback;
Expand Down
1 change: 1 addition & 0 deletions src/choreo/votor/ag_slot_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ struct ag_slot_voted_stake {
fd_bls_agg_t finalize_agg;
ulong notar_or_skip;
ulong top_notar;
ag_block_hash_t top_notar_hash;
};
typedef struct ag_slot_voted_stake ag_slot_voted_stake_t;

Expand Down
Loading
Loading