コード例 #1
0
        public void SignCoinstakeTransactions()
        {
            // Arrange

            // Delete previous wallet and create a new one, mine blocks.
            File.Delete(this.walletName.GetX1WalletFilepath(this.factory.Network, this.factory.DataFolder));
            this.factory.WalletManagerFactory.CreateWallet(new WalletCreateRequest {
                Passphrase = this.passphrase, WalletName = this.walletName
            });

            int  blockMined        = 200;
            long totalMiningReward = 0;

            for (var i = 0; i < blockMined; i++)
            {
                var transactions = new List <Transaction>();

                var zeroOneTwo  = i % 3;
                var addressType = zeroOneTwo == 0 ? AddressType.PubKeyHash :
                                  zeroOneTwo == 1 ? AddressType.ColdStakingHot : AddressType.MultiSig;

                transactions.Add(Create_Wallet.CreateCoinbase(this.factory.ChainIndexer.Tip.Height, this.factory.GetScriptPubKeyForMining(walletName, addressType), this.factory, out var reward));
                totalMiningReward += reward;
                ChainedHeaderBlock nextBlock = this.factory.AddNextBlock(transactions);
            }
            this.factory.SetIBD(false);
            this.factory.SyncToHeight(blockMined, this.walletName);

            var wm = this.factory.WalletManagerFactory.AutoLoad2(this.walletName);

            // Act

            // *** Sign PubKeyHash output
            var budget     = wm.GetBalance(null, AddressType.PubKeyHash);
            var kernelCoin = budget.StakingCoins.First().Value;

            var txPubKeyHash1 = CoinstakeTransactionService.CreateCoinstakeTransaction(kernelCoin, Money.Coins(50).Satoshi, this.date, this.passphrase, out var privateKey1);
            var txPubKeyHash2 = txPubKeyHash1.Clone();

            Assert2.TransactionsEqual(txPubKeyHash1, txPubKeyHash2);

            // sign with TransactionBuilder
            txPubKeyHash1.Sign(C.Network, new[] { privateKey1 }, new ICoin[] { kernelCoin.ToCoin() });
            // sign with SigningService
            SigningService.SignInputs(txPubKeyHash2, new[] { privateKey1 }, new[] { kernelCoin });
            // same valid result?
            Assert2.IsSegWit(txPubKeyHash1);
            Assert2.TransactionsEqual(txPubKeyHash1, txPubKeyHash2);


            // *** Sign ColdStakingHot output
            var coldStakeKernelCoin = wm.GetBalance(null, AddressType.ColdStakingHot).StakingCoins.First().Value;
            var txColdStaking1      = CoinstakeTransactionService.CreateCoinstakeTransaction(coldStakeKernelCoin, Money.Coins(50).Satoshi, this.date, this.passphrase, out var privateKey2);
            var txColdStaking2      = txColdStaking1.Clone();

            Assert2.TransactionsEqual(txColdStaking1, txColdStaking2);

            // sign with TransactionBuilder
            SignScriptAddress(txColdStaking1, privateKey2, coldStakeKernelCoin);
            Assert2.IsSegWit(txColdStaking1);
            // sign with SigningService
            SigningService.SignInputs(txColdStaking2, new[] { privateKey2 }, new [] { coldStakeKernelCoin });
            // same valid result?
            Assert2.TransactionsEqual(txColdStaking1, txColdStaking2);

            // *** Sign MultiSig output
            var multiSigKernelCoin = wm.GetBalance(null, AddressType.MultiSig).StakingCoins.First().Value;

            var txMulti1 = CoinstakeTransactionService.CreateCoinstakeTransaction(multiSigKernelCoin, Money.Coins(50).Satoshi, this.date, this.passphrase, out var privateKey3);
            var txMulti2 = txMulti1.Clone();

            // sign with TransactionBuilder
            SignScriptAddress(txMulti1, privateKey3, multiSigKernelCoin);
            Assert2.IsSegWit(txMulti1);
            // sign with SigningService
            SigningService.SignInputs(txMulti2, new[] { privateKey3 }, new[] { multiSigKernelCoin });
            // same valid result?
            Assert2.TransactionsEqual(txMulti1, txMulti2);
        }
コード例 #2
0
        void CreateNextBlock(BlockTemplate blockTemplate, List <SegWitCoin> kernelCoins)
        {
            SegWitCoin kernelCoin = kernelCoins[0];

            foreach (var coin in kernelCoins)
            {
                if (coin.UtxoValue < kernelCoin.UtxoValue)
                {
                    kernelCoin = coin;
                }
            }

            var newBlockHeight = this.nodeServices.ConsensusManager.Tip.Height + 1;

            var totalReward = blockTemplate.TotalFee + this.nodeServices.PosCoinviewRule.GetProofOfStakeReward(newBlockHeight);

            blockTemplate.Block.Header.Time = (uint)this.PosV3.CurrentBlockTime;

            Transaction tx = CoinstakeTransactionService.CreateAndSignCoinstakeTransaction(kernelCoin, totalReward.Satoshi, (uint)this.PosV3.CurrentBlockTime, this.passphrase, out Key blockSignatureKey);

            if (tx is PosTransaction posTransaction)
            {
                ((PosTransaction)blockTemplate.Block.Transactions[0]).Time = (uint)this.PosV3.CurrentBlockTime;
            }

            blockTemplate.Block.Transactions.Insert(1, tx);

            this.nodeServices.BlockProvider.BlockModified(this.nodeServices.ConsensusManager.Tip, blockTemplate.Block);

            ECDSASignature signature = blockSignatureKey.Sign(blockTemplate.Block.GetHash());

            ((PosBlock)blockTemplate.Block).BlockSignature = new BlockSignature {
                Signature = signature.ToDER()
            };

            ChainedHeader chainedHeader;

            try
            {
                chainedHeader = this.nodeServices.ConsensusManager.BlockMinedAsync(blockTemplate.Block).GetAwaiter().GetResult();
            }
            catch (Exception)
            {
                this.Status.BlocksNotAccepted++;
                throw;
            }

            if (chainedHeader == null)
            {
                this.Status.BlocksNotAccepted += 1;
                return;
            }

            if (this.LastStakedBlock.BlockTime != 0)
            {
                this.Status.ActualTime = (int)(DateTimeOffset.UtcNow.ToUnixTimeSeconds() - this.LastStakedBlock.BlockTime);
            }
            else
            {
                this.Status.ActualTime = (int)(DateTimeOffset.UtcNow.ToUnixTimeSeconds() - this.Status.StartedUtc);
            }

            this.LastStakedBlock.Hash               = chainedHeader.HashBlock;
            this.LastStakedBlock.Height             = chainedHeader.Height;
            this.LastStakedBlock.BlockSize          = chainedHeader.Block.BlockSize ?? -1;
            this.LastStakedBlock.TxId               = chainedHeader.Block.Transactions[1].GetHash();
            this.LastStakedBlock.Transactions       = chainedHeader.Block.Transactions.Count;
            this.LastStakedBlock.TotalReward        = totalReward;
            this.LastStakedBlock.KernelAddress      = kernelCoin.SegWitAddress.Address;
            this.LastStakedBlock.WeightUsed         = kernelCoin.UtxoValue;
            this.LastStakedBlock.TotalComputeTimeMs = this.stopwatch.ElapsedMilliseconds;
            this.LastStakedBlock.BlockTime          = this.PosV3.CurrentBlockTime;
            this.Status.BlocksAccepted             += 1;

            Log.Logger.LogInformation(
                $"Congratulations, your staked a new block at height {newBlockHeight} and received a total reward of {totalReward} {C.Network.CoinTicker}.");
        }