@@ -29,7 +29,7 @@ use common::{
2929 AccountCommand , AccountNonce , ChainstateUpgrade , Destination , OrderData , SignedTransaction ,
3030 TxInput , TxOutput , UtxoOutPoint ,
3131 } ,
32- primitives:: { Amount , BlockHeight , Idable } ,
32+ primitives:: { Amount , BlockHeight , CoinOrTokenId , Idable } ,
3333} ;
3434use crypto:: key:: { KeyKind , PrivateKey } ;
3535use orders_accounting:: OrdersAccountingDB ;
@@ -511,7 +511,7 @@ fn fill_order_check_storage(#[case] seed: Seed) {
511511 tf. make_block_builder ( ) . add_transaction ( tx) . build_and_process ( & mut rng) . unwrap ( ) ;
512512
513513 assert_eq ! (
514- Some ( order_data) ,
514+ Some ( order_data. clone ( ) ) ,
515515 tf. chainstate. get_order_data( & order_id) . unwrap( )
516516 ) ;
517517 assert_eq ! (
@@ -550,7 +550,10 @@ fn fill_order_check_storage(#[case] seed: Seed) {
550550 . build ( ) ;
551551 tf. make_block_builder ( ) . add_transaction ( tx) . build_and_process ( & mut rng) . unwrap ( ) ;
552552
553- assert_eq ! ( None , tf. chainstate. get_order_data( & order_id) . unwrap( ) ) ;
553+ assert_eq ! (
554+ Some ( order_data) ,
555+ tf. chainstate. get_order_data( & order_id) . unwrap( )
556+ ) ;
554557 assert_eq ! (
555558 None ,
556559 tf. chainstate. get_order_ask_balance( & order_id) . unwrap( )
@@ -618,6 +621,79 @@ fn fill_partially_then_conclude(#[case] seed: Seed) {
618621 . build ( ) ;
619622 tf. make_block_builder ( ) . add_transaction ( tx) . build_and_process ( & mut rng) . unwrap ( ) ;
620623
624+ {
625+ // Try overspend give in conclude order
626+ let tx = TransactionBuilder :: new ( )
627+ . add_input (
628+ TxInput :: AccountCommand (
629+ AccountNonce :: new ( 1 ) ,
630+ AccountCommand :: ConcludeOrder ( order_id) ,
631+ ) ,
632+ InputWitness :: NoSignature ( None ) ,
633+ )
634+ . add_output ( TxOutput :: Transfer (
635+ OutputValue :: TokenV1 (
636+ token_id,
637+ ( give_amount - filled_amount)
638+ . and_then ( |v| v + Amount :: from_atoms ( 1 ) )
639+ . unwrap ( ) ,
640+ ) ,
641+ Destination :: AnyoneCanSpend ,
642+ ) )
643+ . add_output ( TxOutput :: Transfer (
644+ OutputValue :: Coin ( output_value_amount ( & fill_value) ) ,
645+ Destination :: AnyoneCanSpend ,
646+ ) )
647+ . build ( ) ;
648+ let tx_id = tx. transaction ( ) . get_id ( ) ;
649+ let res = tf. make_block_builder ( ) . add_transaction ( tx) . build_and_process ( & mut rng) ;
650+ assert_eq ! ( res. unwrap_err( ) ,
651+ chainstate:: ChainstateError :: ProcessBlockError ( chainstate:: BlockError :: StateUpdateFailed (
652+ ConnectTransactionError :: ConstrainedValueAccumulatorError (
653+ constraints_value_accumulator:: Error :: AttemptToPrintMoneyOrViolateTimelockConstraints (
654+ CoinOrTokenId :: TokenId ( token_id)
655+ ) ,
656+ tx_id. into( )
657+ )
658+ ) )
659+ ) ;
660+ }
661+
662+ {
663+ // Try overspend ask in conclude order
664+ let tx = TransactionBuilder :: new ( )
665+ . add_input (
666+ TxInput :: AccountCommand (
667+ AccountNonce :: new ( 1 ) ,
668+ AccountCommand :: ConcludeOrder ( order_id) ,
669+ ) ,
670+ InputWitness :: NoSignature ( None ) ,
671+ )
672+ . add_output ( TxOutput :: Transfer (
673+ OutputValue :: TokenV1 ( token_id, ( give_amount - filled_amount) . unwrap ( ) ) ,
674+ Destination :: AnyoneCanSpend ,
675+ ) )
676+ . add_output ( TxOutput :: Transfer (
677+ OutputValue :: Coin (
678+ ( output_value_amount ( & fill_value) + Amount :: from_atoms ( 1 ) ) . unwrap ( ) ,
679+ ) ,
680+ Destination :: AnyoneCanSpend ,
681+ ) )
682+ . build ( ) ;
683+ let tx_id = tx. transaction ( ) . get_id ( ) ;
684+ let res = tf. make_block_builder ( ) . add_transaction ( tx) . build_and_process ( & mut rng) ;
685+ assert_eq ! ( res. unwrap_err( ) ,
686+ chainstate:: ChainstateError :: ProcessBlockError ( chainstate:: BlockError :: StateUpdateFailed (
687+ ConnectTransactionError :: ConstrainedValueAccumulatorError (
688+ constraints_value_accumulator:: Error :: AttemptToPrintMoneyOrViolateTimelockConstraints (
689+ CoinOrTokenId :: Coin
690+ ) ,
691+ tx_id. into( )
692+ )
693+ ) )
694+ ) ;
695+ }
696+
621697 // conclude the order
622698 let tx = TransactionBuilder :: new ( )
623699 . add_input (
@@ -650,6 +726,190 @@ fn fill_partially_then_conclude(#[case] seed: Seed) {
650726 } ) ;
651727}
652728
729+ #[ rstest]
730+ #[ trace]
731+ #[ case( Seed :: from_entropy( ) ) ]
732+ fn fill_completely_then_conclude ( #[ case] seed : Seed ) {
733+ utils:: concurrency:: model ( move || {
734+ let mut rng = make_seedable_rng ( seed) ;
735+ let mut tf = TestFramework :: builder ( & mut rng) . build ( ) ;
736+
737+ let ( token_id, tokens_outpoint, coins_outpoint) =
738+ issue_and_mint_token_from_genesis ( & mut rng, & mut tf) ;
739+
740+ let ask_amount = Amount :: from_atoms ( rng. gen_range ( 1u128 ..1000 ) ) ;
741+ let give_amount = Amount :: from_atoms ( rng. gen_range ( 1u128 ..1000 ) ) ;
742+ let order_data = OrderData :: new (
743+ Destination :: AnyoneCanSpend ,
744+ OutputValue :: Coin ( ask_amount) ,
745+ OutputValue :: TokenV1 ( token_id, give_amount) ,
746+ ) ;
747+
748+ let order_id = make_order_id ( & tokens_outpoint) ;
749+ let tx = TransactionBuilder :: new ( )
750+ . add_input ( tokens_outpoint. into ( ) , InputWitness :: NoSignature ( None ) )
751+ . add_output ( TxOutput :: AnyoneCanTake ( Box :: new ( order_data) ) )
752+ . build ( ) ;
753+ tf. make_block_builder ( ) . add_transaction ( tx) . build_and_process ( & mut rng) . unwrap ( ) ;
754+
755+ {
756+ // Try overspend complete fill order
757+ let tx = TransactionBuilder :: new ( )
758+ . add_input (
759+ coins_outpoint. clone ( ) . into ( ) ,
760+ InputWitness :: NoSignature ( None ) ,
761+ )
762+ . add_input (
763+ TxInput :: AccountCommand (
764+ AccountNonce :: new ( 0 ) ,
765+ AccountCommand :: FillOrder (
766+ order_id,
767+ OutputValue :: Coin ( ask_amount) ,
768+ Destination :: AnyoneCanSpend ,
769+ ) ,
770+ ) ,
771+ InputWitness :: NoSignature ( None ) ,
772+ )
773+ . add_output ( TxOutput :: Transfer (
774+ OutputValue :: TokenV1 ( token_id, ( give_amount + Amount :: from_atoms ( 1 ) ) . unwrap ( ) ) ,
775+ Destination :: AnyoneCanSpend ,
776+ ) )
777+ . build ( ) ;
778+ let tx_id = tx. transaction ( ) . get_id ( ) ;
779+ let res = tf. make_block_builder ( ) . add_transaction ( tx) . build_and_process ( & mut rng) ;
780+ assert_eq ! ( res. unwrap_err( ) ,
781+ chainstate:: ChainstateError :: ProcessBlockError ( chainstate:: BlockError :: StateUpdateFailed (
782+ ConnectTransactionError :: ConstrainedValueAccumulatorError (
783+ constraints_value_accumulator:: Error :: AttemptToPrintMoneyOrViolateTimelockConstraints (
784+ CoinOrTokenId :: TokenId ( token_id)
785+ ) ,
786+ tx_id. into( )
787+ )
788+ ) )
789+ ) ;
790+ }
791+
792+ {
793+ // Try overbid complete fill order
794+ let tx = TransactionBuilder :: new ( )
795+ . add_input (
796+ coins_outpoint. clone ( ) . into ( ) ,
797+ InputWitness :: NoSignature ( None ) ,
798+ )
799+ . add_input (
800+ TxInput :: AccountCommand (
801+ AccountNonce :: new ( 0 ) ,
802+ AccountCommand :: FillOrder (
803+ order_id,
804+ OutputValue :: Coin ( ( ask_amount + Amount :: from_atoms ( 1 ) ) . unwrap ( ) ) ,
805+ Destination :: AnyoneCanSpend ,
806+ ) ,
807+ ) ,
808+ InputWitness :: NoSignature ( None ) ,
809+ )
810+ . add_output ( TxOutput :: Transfer (
811+ OutputValue :: TokenV1 ( token_id, give_amount) ,
812+ Destination :: AnyoneCanSpend ,
813+ ) )
814+ . build ( ) ;
815+ let tx_id = tx. transaction ( ) . get_id ( ) ;
816+ let res = tf. make_block_builder ( ) . add_transaction ( tx) . build_and_process ( & mut rng) ;
817+ assert_eq ! (
818+ res. unwrap_err( ) ,
819+ chainstate:: ChainstateError :: ProcessBlockError (
820+ chainstate:: BlockError :: StateUpdateFailed (
821+ ConnectTransactionError :: ConstrainedValueAccumulatorError (
822+ orders_accounting:: Error :: OrderOverbid (
823+ order_id,
824+ ask_amount,
825+ ( ask_amount + Amount :: from_atoms( 1 ) ) . unwrap( )
826+ )
827+ . into( ) ,
828+ tx_id. into( )
829+ )
830+ )
831+ )
832+ ) ;
833+ }
834+
835+ // Fill the order completely
836+ let tx = TransactionBuilder :: new ( )
837+ . add_input ( coins_outpoint. into ( ) , InputWitness :: NoSignature ( None ) )
838+ . add_input (
839+ TxInput :: AccountCommand (
840+ AccountNonce :: new ( 0 ) ,
841+ AccountCommand :: FillOrder (
842+ order_id,
843+ OutputValue :: Coin ( ask_amount) ,
844+ Destination :: AnyoneCanSpend ,
845+ ) ,
846+ ) ,
847+ InputWitness :: NoSignature ( None ) ,
848+ )
849+ . add_output ( TxOutput :: Transfer (
850+ OutputValue :: TokenV1 ( token_id, give_amount) ,
851+ Destination :: AnyoneCanSpend ,
852+ ) )
853+ . build ( ) ;
854+ tf. make_block_builder ( ) . add_transaction ( tx) . build_and_process ( & mut rng) . unwrap ( ) ;
855+
856+ {
857+ // Try overspend conclude order
858+ let tx = TransactionBuilder :: new ( )
859+ . add_input (
860+ TxInput :: AccountCommand (
861+ AccountNonce :: new ( 1 ) ,
862+ AccountCommand :: ConcludeOrder ( order_id) ,
863+ ) ,
864+ InputWitness :: NoSignature ( None ) ,
865+ )
866+ . add_output ( TxOutput :: Transfer (
867+ OutputValue :: Coin ( ( ask_amount + Amount :: from_atoms ( 1 ) ) . unwrap ( ) ) ,
868+ Destination :: AnyoneCanSpend ,
869+ ) )
870+ . build ( ) ;
871+ let tx_id = tx. transaction ( ) . get_id ( ) ;
872+ let res = tf. make_block_builder ( ) . add_transaction ( tx) . build_and_process ( & mut rng) ;
873+ assert_eq ! ( res. unwrap_err( ) ,
874+ chainstate:: ChainstateError :: ProcessBlockError ( chainstate:: BlockError :: StateUpdateFailed (
875+ ConnectTransactionError :: ConstrainedValueAccumulatorError (
876+ constraints_value_accumulator:: Error :: AttemptToPrintMoneyOrViolateTimelockConstraints (
877+ CoinOrTokenId :: Coin
878+ ) ,
879+ tx_id. into( )
880+ )
881+ ) )
882+ ) ;
883+ }
884+
885+ // conclude the order
886+ let tx = TransactionBuilder :: new ( )
887+ . add_input (
888+ TxInput :: AccountCommand (
889+ AccountNonce :: new ( 1 ) ,
890+ AccountCommand :: ConcludeOrder ( order_id) ,
891+ ) ,
892+ InputWitness :: NoSignature ( None ) ,
893+ )
894+ . add_output ( TxOutput :: Transfer (
895+ OutputValue :: Coin ( ask_amount) ,
896+ Destination :: AnyoneCanSpend ,
897+ ) )
898+ . build ( ) ;
899+ tf. make_block_builder ( ) . add_transaction ( tx) . build_and_process ( & mut rng) . unwrap ( ) ;
900+
901+ assert_eq ! ( None , tf. chainstate. get_order_data( & order_id) . unwrap( ) ) ;
902+ assert_eq ! (
903+ None ,
904+ tf. chainstate. get_order_ask_balance( & order_id) . unwrap( )
905+ ) ;
906+ assert_eq ! (
907+ None ,
908+ tf. chainstate. get_order_give_balance( & order_id) . unwrap( )
909+ ) ;
910+ } ) ;
911+ }
912+
653913#[ rstest]
654914#[ trace]
655915#[ case( Seed :: from_entropy( ) ) ]
0 commit comments