@@ -507,7 +507,7 @@ static bool is_valid_price_upd( cmd_upd_price_t *cptr, SolAccountInfo *price_acc
507507
508508 // Reject if this price corresponds to the same or earlier time
509509 pc_price_info_t * fptr = & pptr -> comp_ [comp_idx ].latest_ ;
510- if ( cptr -> cmd_ == e_cmd_upd_price &&
510+ if ( ( cptr -> cmd_ == e_cmd_upd_price || cptr -> cmd_ == e_cmd_batch_upd_price ) &&
511511 cptr -> pub_slot_ <= fptr -> pub_slot_ ) {
512512 return false;
513513 }
@@ -525,14 +525,72 @@ static void do_price_upd( cmd_upd_price_t *cptr, SolAccountInfo *clock_account,
525525
526526 // update component price if required
527527 pc_price_info_t * fptr = & pptr -> comp_ [comp_idx ].latest_ ;
528- if ( cptr -> cmd_ == e_cmd_upd_price ) {
528+ if ( ( cptr -> cmd_ == e_cmd_upd_price || cptr -> cmd_ == e_cmd_batch_upd_price ) ) {
529529 fptr -> price_ = cptr -> price_ ;
530530 fptr -> conf_ = cptr -> conf_ ;
531531 fptr -> status_ = cptr -> status_ ;
532532 fptr -> pub_slot_ = cptr -> pub_slot_ ;
533533 }
534534}
535535
536+ static uint64_t batch_upd_price ( SolParameters * prm , SolAccountInfo * ka ) {
537+ // Check that header information has been provided
538+ if ( prm -> data_len < sizeof ( cmd_batch_upd_price_header_t ) ) {
539+ return ERROR_INVALID_ARGUMENT ;
540+ }
541+ cmd_batch_upd_price_header_t * hptr = (cmd_batch_upd_price_header_t * )prm -> data ;
542+
543+ // Check that within the batch, the correct number of updates have been provided
544+ if ( prm -> data_len != ( sizeof ( cmd_batch_upd_price_header_t ) + ( hptr -> count_ * sizeof ( cmd_upd_price_t ) ) ) ) {
545+ return ERROR_INVALID_ARGUMENT ;
546+ }
547+ cmd_batch_upd_price_t * cptr = (cmd_batch_upd_price_t * )prm -> data ;
548+
549+ // Check that the correct number of account keys have been provided.
550+ // We expect the publisher account, the clock account and the price accounts to be present.
551+ if ( prm -> ka_num != ( 2 + hptr -> count_ ) ) {
552+ return ERROR_INVALID_ARGUMENT ;
553+ }
554+ SolAccountInfo * publish_account = & ka [0 ];
555+ SolAccountInfo * clock_account = & ka [hptr -> count_ + 1 ];
556+
557+ // Check that the publish accounts and the clock accounts are valid
558+ if ( !valid_funding_account ( publish_account ) ||
559+ !pc_pub_key_equal ( (pc_pub_key_t * )clock_account -> key , (pc_pub_key_t * )sysvar_clock ) ) {
560+ return ERROR_INVALID_ARGUMENT ;
561+ }
562+
563+ // Loop over all the given updates.
564+ bool any_succeeded = false;
565+ for ( uint64_t i = 0 ; i < hptr -> count_ ; i ++ ) {
566+
567+ cmd_upd_price_t * uptr = & cptr -> upds_ [i ];
568+ SolAccountInfo * price_account = & ka [1 + i ];
569+
570+ // Check that the price account is signed, writable with the correct ownership and is of the correct size
571+ if ( !valid_writable_account ( prm , price_account , sizeof ( pc_price_t ) ) ) {
572+ continue ;
573+ }
574+
575+ // Check that this price update is valid
576+ uint32_t comp_idx = find_comp_idx ( publish_account , price_account );
577+ if ( !is_valid_price_upd ( uptr , price_account , comp_idx ) ) {
578+ continue ;
579+ }
580+
581+ do_price_upd ( uptr , clock_account , price_account , comp_idx );
582+
583+ any_succeeded = true;
584+ }
585+
586+ // Fail the transaction if no updates succeeded
587+ if ( !any_succeeded && hptr -> count_ > 0 ) {
588+ return ERROR_INVALID_ARGUMENT ;
589+ }
590+
591+ return SUCCESS ;
592+ }
593+
536594static uint64_t upd_price ( SolParameters * prm , SolAccountInfo * ka )
537595{
538596 // Validate command parameters
@@ -581,25 +639,30 @@ static uint64_t dispatch( SolParameters *prm, SolAccountInfo *ka )
581639 }
582640 switch (hdr -> cmd_ ) {
583641 case e_cmd_upd_price :
584- case e_cmd_agg_price : return upd_price ( prm , ka );
585- case e_cmd_init_mapping : return init_mapping ( prm , ka );
586- case e_cmd_add_mapping : return add_mapping ( prm , ka );
587- case e_cmd_add_product : return add_product ( prm , ka );
588- case e_cmd_upd_product : return upd_product ( prm , ka );
589- case e_cmd_add_price : return add_price ( prm , ka );
590- case e_cmd_add_publisher : return add_publisher ( prm , ka );
591- case e_cmd_del_publisher : return del_publisher ( prm , ka );
592- case e_cmd_init_price : return init_price ( prm , ka );
593- case e_cmd_init_test : return init_test ( prm , ka );
594- case e_cmd_upd_test : return upd_test ( prm , ka );
595- case e_cmd_set_min_pub : return set_min_pub ( prm , ka );
596- default : return ERROR_INVALID_ARGUMENT ;
642+ case e_cmd_agg_price : return upd_price ( prm , ka );
643+ case e_cmd_batch_upd_price : return batch_upd_price ( prm , ka );
644+ case e_cmd_init_mapping : return init_mapping ( prm , ka );
645+ case e_cmd_add_mapping : return add_mapping ( prm , ka );
646+ case e_cmd_add_product : return add_product ( prm , ka );
647+ case e_cmd_upd_product : return upd_product ( prm , ka );
648+ case e_cmd_add_price : return add_price ( prm , ka );
649+ case e_cmd_add_publisher : return add_publisher ( prm , ka );
650+ case e_cmd_del_publisher : return del_publisher ( prm , ka );
651+ case e_cmd_init_price : return init_price ( prm , ka );
652+ case e_cmd_init_test : return init_test ( prm , ka );
653+ case e_cmd_upd_test : return upd_test ( prm , ka );
654+ case e_cmd_set_min_pub : return set_min_pub ( prm , ka );
655+ default : return ERROR_INVALID_ARGUMENT ;
597656 }
598657}
599658
600659extern uint64_t entrypoint (const uint8_t * input )
601660{
602- SolAccountInfo ka [4 ];
661+ // Batch transactions contain a price account for each symbol,
662+ // the publishing account and the sysvar_clock account.
663+ int16_t num_accounts = MAX_BATCH_UPD_PRICE_COUNT + 2 ;
664+ SolAccountInfo ka [num_accounts ];
665+
603666 SolParameters prm [1 ];
604667 prm -> ka = ka ;
605668 if (!sol_deserialize (input , prm , SOL_ARRAY_SIZE (ka ))) {
0 commit comments