@@ -568,3 +568,278 @@ func TestV2TransactionChainIndices(t *testing.T) {
568568 n .assertV2ChainIndices (t , txn1 .ID ())
569569 n .assertV2ChainIndices (t , txn2 .ID ())
570570}
571+
572+ func TestSiacoinBalance (t * testing.T ) {
573+ pk1 := types .GeneratePrivateKey ()
574+ uc1 := types .StandardUnlockConditions (pk1 .PublicKey ())
575+ addr1 := uc1 .UnlockHash ()
576+
577+ pk2 := types .GeneratePrivateKey ()
578+ uc2 := types .StandardUnlockConditions (pk2 .PublicKey ())
579+ addr2 := uc2 .UnlockHash ()
580+
581+ n := newTestChain (t , false , func (network * consensus.Network , genesisBlock types.Block ) {
582+ genesisBlock .Transactions [0 ].SiacoinOutputs [0 ].Address = addr1
583+ })
584+ val := n .genesis ().Transactions [0 ].SiacoinOutputs [0 ].Value
585+
586+ checkBalance := func (addr types.Address , expectedSC , expectedImmatureSC types.Currency ) {
587+ t .Helper ()
588+
589+ sc , immatureSC , sf , err := n .db .Balance (addr )
590+ if err != nil {
591+ t .Fatal (err )
592+ }
593+ testutil .Equal (t , "siacoins" , expectedSC , sc )
594+ testutil .Equal (t , "immature siacoins" , expectedImmatureSC , immatureSC )
595+ testutil .Equal (t , "siafunds" , 0 , sf )
596+ }
597+
598+ // only addr1 should have SC from genesis block
599+ checkBalance (types .VoidAddress , types .ZeroCurrency , types .ZeroCurrency )
600+ checkBalance (addr1 , val , types .ZeroCurrency )
601+ checkBalance (addr2 , types .ZeroCurrency , types .ZeroCurrency )
602+
603+ txn1 := types.Transaction {
604+ SiacoinInputs : []types.SiacoinInput {{
605+ ParentID : n .genesis ().Transactions [0 ].SiacoinOutputID (0 ),
606+ UnlockConditions : uc1 ,
607+ }},
608+ SiacoinOutputs : []types.SiacoinOutput {{
609+ Address : addr2 ,
610+ Value : val ,
611+ }},
612+ }
613+ testutil .SignTransaction (n .tipState (), pk1 , & txn1 )
614+
615+ // send addr1 output to addr2
616+ b := testutil .MineBlock (n .tipState (), []types.Transaction {txn1 }, types .VoidAddress )
617+ n .applyBlock (t , b )
618+
619+ // addr2 should have SC and the void address should have immature SC from
620+ // block
621+ checkBalance (types .VoidAddress , types .ZeroCurrency , b .MinerPayouts [0 ].Value )
622+ checkBalance (addr1 , types .ZeroCurrency , types .ZeroCurrency )
623+ checkBalance (addr2 , val , types .ZeroCurrency )
624+
625+ n .revertBlock (t )
626+
627+ // after revert, addr1 should have funds again and the void address should
628+ // have nothing
629+ checkBalance (types .VoidAddress , types .ZeroCurrency , types .ZeroCurrency )
630+ checkBalance (addr1 , val , types .ZeroCurrency )
631+ checkBalance (addr2 , types .ZeroCurrency , types .ZeroCurrency )
632+ }
633+
634+ func TestSiafundBalance (t * testing.T ) {
635+ pk1 := types .GeneratePrivateKey ()
636+ uc1 := types .StandardUnlockConditions (pk1 .PublicKey ())
637+ addr1 := uc1 .UnlockHash ()
638+
639+ pk2 := types .GeneratePrivateKey ()
640+ uc2 := types .StandardUnlockConditions (pk2 .PublicKey ())
641+ addr2 := uc2 .UnlockHash ()
642+
643+ n := newTestChain (t , false , func (network * consensus.Network , genesisBlock types.Block ) {
644+ genesisBlock .Transactions [0 ].SiafundOutputs [0 ].Address = addr1
645+ })
646+ val := n .genesis ().Transactions [0 ].SiafundOutputs [0 ].Value
647+
648+ checkBalance := func (addr types.Address , expectedSF uint64 ) {
649+ t .Helper ()
650+
651+ sc , immatureSC , sf , err := n .db .Balance (addr )
652+ if err != nil {
653+ t .Fatal (err )
654+ }
655+ testutil .Equal (t , "siacoins" , types .ZeroCurrency , sc )
656+ if addr != types .VoidAddress {
657+ testutil .Equal (t , "immature siacoins" , types .ZeroCurrency , immatureSC )
658+ }
659+ testutil .Equal (t , "siafunds" , expectedSF , sf )
660+ }
661+
662+ // addr1 should have SF from genesis block
663+ checkBalance (types .VoidAddress , 0 )
664+ checkBalance (addr1 , val )
665+ checkBalance (addr2 , 0 )
666+
667+ txn1 := types.Transaction {
668+ SiafundInputs : []types.SiafundInput {{
669+ ParentID : n .genesis ().Transactions [0 ].SiafundOutputID (0 ),
670+ UnlockConditions : uc1 ,
671+ }},
672+ SiafundOutputs : []types.SiafundOutput {{
673+ Address : addr2 ,
674+ Value : val ,
675+ }},
676+ }
677+ testutil .SignTransaction (n .tipState (), pk1 , & txn1 )
678+
679+ // send addr1 SF to addr2
680+ n .mineTransactions (t , txn1 )
681+
682+ // addr2 should have SF now
683+ checkBalance (types .VoidAddress , 0 )
684+ checkBalance (addr1 , 0 )
685+ checkBalance (addr2 , val )
686+
687+ n .revertBlock (t )
688+
689+ // after revert, addr1 should have SF again
690+ checkBalance (types .VoidAddress , 0 )
691+ checkBalance (addr1 , val )
692+ checkBalance (addr2 , 0 )
693+ }
694+
695+ func TestEphemeralSiacoinBalance (t * testing.T ) {
696+ pk1 := types .GeneratePrivateKey ()
697+ uc1 := types .StandardUnlockConditions (pk1 .PublicKey ())
698+ addr1 := uc1 .UnlockHash ()
699+
700+ pk2 := types .GeneratePrivateKey ()
701+ uc2 := types .StandardUnlockConditions (pk2 .PublicKey ())
702+ addr2 := uc2 .UnlockHash ()
703+
704+ pk3 := types .GeneratePrivateKey ()
705+ uc3 := types .StandardUnlockConditions (pk3 .PublicKey ())
706+ addr3 := uc3 .UnlockHash ()
707+
708+ n := newTestChain (t , false , func (network * consensus.Network , genesisBlock types.Block ) {
709+ genesisBlock .Transactions [0 ].SiacoinOutputs [0 ].Address = addr1
710+ })
711+ val := n .genesis ().Transactions [0 ].SiacoinOutputs [0 ].Value
712+
713+ checkBalance := func (addr types.Address , expectedSC types.Currency ) {
714+ t .Helper ()
715+
716+ sc , immatureSC , sf , err := n .db .Balance (addr )
717+ if err != nil {
718+ t .Fatal (err )
719+ }
720+ testutil .Equal (t , "siacoins" , expectedSC , sc )
721+ testutil .Equal (t , "immature siacoins" , types .ZeroCurrency , immatureSC )
722+ testutil .Equal (t , "siafunds" , 0 , sf )
723+ }
724+
725+ // only addr1 should have SC from genesis block
726+ checkBalance (addr1 , val )
727+ checkBalance (addr2 , types .ZeroCurrency )
728+ checkBalance (addr3 , types .ZeroCurrency )
729+
730+ txn1 := types.Transaction {
731+ SiacoinInputs : []types.SiacoinInput {{
732+ ParentID : n .genesis ().Transactions [0 ].SiacoinOutputID (0 ),
733+ UnlockConditions : uc1 ,
734+ }},
735+ SiacoinOutputs : []types.SiacoinOutput {{
736+ Address : addr2 ,
737+ Value : val ,
738+ }},
739+ }
740+ testutil .SignTransaction (n .tipState (), pk1 , & txn1 )
741+
742+ txn2 := types.Transaction {
743+ SiacoinInputs : []types.SiacoinInput {{
744+ ParentID : txn1 .SiacoinOutputID (0 ),
745+ UnlockConditions : uc2 ,
746+ }},
747+ SiacoinOutputs : []types.SiacoinOutput {{
748+ Address : addr3 ,
749+ Value : val ,
750+ }},
751+ }
752+ testutil .SignTransaction (n .tipState (), pk2 , & txn2 )
753+
754+ // net effect of txn1 and txn2 is to send addr1 output to addr3
755+ n .mineTransactions (t , txn1 , txn2 )
756+
757+ // addr3 should have all the value now
758+ checkBalance (addr1 , types .ZeroCurrency )
759+ checkBalance (addr2 , types .ZeroCurrency )
760+ checkBalance (addr3 , val )
761+
762+ n .revertBlock (t )
763+
764+ // after revert, addr1 should have funds again and the others should
765+ // have nothing
766+ checkBalance (addr1 , val )
767+ checkBalance (addr2 , types .ZeroCurrency )
768+ checkBalance (addr3 , types .ZeroCurrency )
769+ }
770+
771+ func TestEphemeralSiafundBalance (t * testing.T ) {
772+ pk1 := types .GeneratePrivateKey ()
773+ uc1 := types .StandardUnlockConditions (pk1 .PublicKey ())
774+ addr1 := uc1 .UnlockHash ()
775+
776+ pk2 := types .GeneratePrivateKey ()
777+ uc2 := types .StandardUnlockConditions (pk2 .PublicKey ())
778+ addr2 := uc2 .UnlockHash ()
779+
780+ pk3 := types .GeneratePrivateKey ()
781+ uc3 := types .StandardUnlockConditions (pk3 .PublicKey ())
782+ addr3 := uc3 .UnlockHash ()
783+
784+ n := newTestChain (t , false , func (network * consensus.Network , genesisBlock types.Block ) {
785+ genesisBlock .Transactions [0 ].SiafundOutputs [0 ].Address = addr1
786+ })
787+ val := n .genesis ().Transactions [0 ].SiafundOutputs [0 ].Value
788+
789+ checkBalance := func (addr types.Address , expectedSF uint64 ) {
790+ t .Helper ()
791+
792+ sc , immatureSC , sf , err := n .db .Balance (addr )
793+ if err != nil {
794+ t .Fatal (err )
795+ }
796+ testutil .Equal (t , "siacoins" , types .ZeroCurrency , sc )
797+ testutil .Equal (t , "immature siacoins" , types .ZeroCurrency , immatureSC )
798+ testutil .Equal (t , "siafunds" , expectedSF , sf )
799+ }
800+
801+ // only addr1 should have SF from genesis block
802+ checkBalance (addr1 , val )
803+ checkBalance (addr2 , 0 )
804+ checkBalance (addr3 , 0 )
805+
806+ txn1 := types.Transaction {
807+ SiafundInputs : []types.SiafundInput {{
808+ ParentID : n .genesis ().Transactions [0 ].SiafundOutputID (0 ),
809+ UnlockConditions : uc1 ,
810+ }},
811+ SiafundOutputs : []types.SiafundOutput {{
812+ Address : addr2 ,
813+ Value : val ,
814+ }},
815+ }
816+ testutil .SignTransaction (n .tipState (), pk1 , & txn1 )
817+
818+ txn2 := types.Transaction {
819+ SiafundInputs : []types.SiafundInput {{
820+ ParentID : txn1 .SiafundOutputID (0 ),
821+ UnlockConditions : uc2 ,
822+ }},
823+ SiafundOutputs : []types.SiafundOutput {{
824+ Address : addr3 ,
825+ Value : val ,
826+ }},
827+ }
828+ testutil .SignTransaction (n .tipState (), pk2 , & txn2 )
829+
830+ // net effect of txn1 and txn2 is to send addr1 output to addr3
831+ n .mineTransactions (t , txn1 , txn2 )
832+
833+ // addr3 should have all the value now
834+ checkBalance (addr1 , 0 )
835+ checkBalance (addr2 , 0 )
836+ checkBalance (addr3 , val )
837+
838+ n .revertBlock (t )
839+
840+ // after revert, addr1 should have funds again and the others should
841+ // have nothing
842+ checkBalance (addr1 , val )
843+ checkBalance (addr2 , 0 )
844+ checkBalance (addr3 , 0 )
845+ }
0 commit comments