@@ -566,7 +566,7 @@ pub fn disconnect_tip(
566566 rwtxn,
567567 & filled_tx,
568568 ( * * bitname_updates) . clone ( ) ,
569- height - 1 ,
569+ height,
570570 ) ?;
571571 }
572572 Some ( TxData :: BatchIcann ( batch_icann_data) ) => {
@@ -650,3 +650,164 @@ pub fn disconnect_tip(
650650 }
651651 Ok ( ( ) )
652652}
653+
654+ #[ cfg( test) ]
655+ mod test {
656+ use bitcoin:: hashes:: Hash as _;
657+
658+ use crate :: {
659+ authorization:: { self , SigningKey } ,
660+ state:: {
661+ block:: { connect, disconnect_tip, validate} ,
662+ test:: fresh_state,
663+ } ,
664+ types:: {
665+ BitName , BitNameDataUpdates , BitNameSeqId , BlockHash , Body ,
666+ FilledOutput , FilledOutputContent , FilledTransaction , Hash , Header ,
667+ MerkleRoot , MutableBitNameData , OutPoint , OutPointKey , Output ,
668+ OutputContent , Transaction , TxData , Update ,
669+ } ,
670+ } ;
671+
672+ fn header (
673+ prev_side_hash : Option < BlockHash > ,
674+ merkle_root : MerkleRoot ,
675+ ) -> Header {
676+ Header {
677+ merkle_root,
678+ prev_side_hash,
679+ prev_main_hash : bitcoin:: BlockHash :: from_byte_array ( [ 0 ; 32 ] ) ,
680+ }
681+ }
682+
683+ fn all_retained_updates ( ) -> BitNameDataUpdates {
684+ BitNameDataUpdates {
685+ commitment : Update :: Retain ,
686+ socket_addr_v4 : Update :: Retain ,
687+ socket_addr_v6 : Update :: Retain ,
688+ encryption_pubkey : Update :: Retain ,
689+ signing_pubkey : Update :: Retain ,
690+ paymail_fee_sats : Update :: Retain ,
691+ }
692+ }
693+
694+ #[ test]
695+ fn disconnect_bitname_data_update ( ) -> anyhow:: Result < ( ) > {
696+ let ( env, state) = fresh_state ( "disconnect_bitname_data_update" ) ?;
697+ let signing_key = SigningKey :: from_bytes ( & [ 7 ; 32 ] ) ;
698+ let verifying_key = signing_key. verifying_key ( ) . into ( ) ;
699+ let address = authorization:: get_address ( & verifying_key) ;
700+
701+ let name_hash: Hash = [ 1 ; 32 ] ;
702+ let revealed_nonce: Hash = [ 2 ; 32 ] ;
703+ let commitment: Hash =
704+ blake3:: keyed_hash ( & revealed_nonce, & name_hash) . into ( ) ;
705+ let reservation_txid = [ 3 ; 32 ] . into ( ) ;
706+ let bitname = BitName ( name_hash) ;
707+ let bitname_outpoint = OutPoint :: Regular {
708+ txid : [ 5 ; 32 ] . into ( ) ,
709+ vout : 0 ,
710+ } ;
711+
712+ {
713+ let mut rwtxn = env. write_txn ( ) ?;
714+ state. bitnames . put_reservation (
715+ & mut rwtxn,
716+ & reservation_txid,
717+ & commitment,
718+ ) ?;
719+ let registration_tx = Transaction {
720+ inputs : vec ! [ OutPoint :: Regular {
721+ txid: reservation_txid,
722+ vout: 0 ,
723+ } ] ,
724+ outputs : Vec :: new ( ) ,
725+ memo : Vec :: new ( ) ,
726+ data : Some ( TxData :: BitNameRegistration {
727+ name_hash : bitname,
728+ revealed_nonce,
729+ bitname_data : Box :: new ( MutableBitNameData :: default ( ) ) ,
730+ } ) ,
731+ } ;
732+ let registration_filled = crate :: types:: FilledTransaction {
733+ transaction : registration_tx,
734+ spent_utxos : vec ! [ FilledOutput {
735+ address,
736+ content: FilledOutputContent :: BitNameReservation (
737+ reservation_txid,
738+ commitment,
739+ ) ,
740+ memo: Vec :: new( ) ,
741+ } ] ,
742+ } ;
743+ state. bitnames . apply_registration (
744+ & mut rwtxn,
745+ & registration_filled,
746+ bitname,
747+ & MutableBitNameData :: default ( ) ,
748+ 0 ,
749+ ) ?;
750+ let seq = state. bitnames . next_seq ( & rwtxn) ?;
751+ anyhow:: ensure!( seq == BitNameSeqId :: new( 1 ) ) ;
752+ state. utxos . put (
753+ & mut rwtxn,
754+ & OutPointKey :: from_outpoint ( & bitname_outpoint) ,
755+ & FilledOutput {
756+ address,
757+ content : FilledOutputContent :: BitName ( bitname) ,
758+ memo : Vec :: new ( ) ,
759+ } ,
760+ ) ?;
761+ rwtxn. commit ( ) ?;
762+ }
763+
764+ let genesis_body = Body {
765+ coinbase : Vec :: new ( ) ,
766+ transactions : Vec :: new ( ) ,
767+ authorizations : Vec :: new ( ) ,
768+ } ;
769+ let genesis_merkle_root =
770+ Body :: compute_merkle_root :: < FilledTransaction > ( & [ ] , & [ ] ) ?;
771+ let genesis_header = header ( None , genesis_merkle_root) ;
772+ {
773+ let mut rwtxn = env. write_txn ( ) ?;
774+ connect ( & state, & mut rwtxn, & genesis_header, & genesis_body) ?;
775+ rwtxn. commit ( ) ?;
776+ }
777+
778+ let mut updates = all_retained_updates ( ) ;
779+ updates. commitment = Update :: Set ( [ 9 ; 32 ] ) ;
780+ let update_tx = Transaction {
781+ inputs : vec ! [ bitname_outpoint] ,
782+ outputs : vec ! [ Output :: new( address, OutputContent :: BitName ) ] ,
783+ memo : Vec :: new ( ) ,
784+ data : Some ( TxData :: BitNameUpdate ( Box :: new ( updates) ) ) ,
785+ } ;
786+ let filled_update_tx = {
787+ let rotxn = env. read_txn ( ) ?;
788+ state. fill_transaction ( & rotxn, & update_tx) ?
789+ } ;
790+ let authorized_update =
791+ authorization:: authorize ( & [ ( address, & signing_key) ] , update_tx) ?;
792+ let update_body = Body :: new ( vec ! [ authorized_update] , Vec :: new ( ) ) ;
793+ let update_merkle_root =
794+ Body :: compute_merkle_root ( & [ ] , & [ filled_update_tx] ) ?;
795+ let update_header =
796+ header ( Some ( genesis_header. hash ( ) ) , update_merkle_root) ;
797+
798+ {
799+ let rotxn = env. read_txn ( ) ?;
800+ validate ( & state, & rotxn, & update_header, & update_body) ?;
801+ }
802+ {
803+ let mut rwtxn = env. write_txn ( ) ?;
804+ connect ( & state, & mut rwtxn, & update_header, & update_body) ?;
805+ rwtxn. commit ( ) ?;
806+ }
807+
808+ let mut rwtxn = env. write_txn ( ) ?;
809+ let ( ) =
810+ disconnect_tip ( & state, & mut rwtxn, & update_header, & update_body) ?;
811+ Ok ( ( ) )
812+ }
813+ }
0 commit comments