예제 #1
0
        public async Task <bool> CheckChainAsync(IReadOnlyList <Block> blockchainToValidate)
        {
            // Check if the genesis block is the same
            if (_hashProvider.ComputeHashString(blockchainToValidate[0]) !=
                _hashProvider.ComputeHashString(await _blocks.GetGenesisBlockAsync()))
            {
                var message = $"Genesis blocks aren't the same";
                _logger?.LogError(message);
                throw new BlockchainAssertionException(message);
            }

            // Compare every block to the previous one (it skips the first one, because it was verified before)
            try
            {
                for (var i = 1; i < blockchainToValidate.Count; i++)
                {
                    CheckBlock(blockchainToValidate[i], blockchainToValidate[i - 1]);
                }
            }
            catch (Exception ex)
            {
                var message = $"Invalid block sequence";
                _logger?.LogError(message);
                throw new BlockchainAssertionException(message, ex);
            }

            return(true);
        }
예제 #2
0
        public Transaction Build()
        {
            // Check required information
            if (_utxo == null)
            {
                throw new ArgumentException($"It's necessary to provide a list of unspent output transactions.");
            }
            if (_outputAddress == null)
            {
                throw new ArgumentException($"It's necessary to provide the destination address.");
            }
            if (_totalAmount == null)
            {
                throw new ArgumentException($"It's necessary to provide the transaction value.");
            }

            // Calculates the change amount
            var changeAmount = _utxo.Sum(x => x.Amount) - _totalAmount - _feeAmount;

            var transactionId = CryptoUtil.RandomString();

            // For each transaction input, calculates the hash of the input and signs the data
            var inputIndex = 1;
            var inputs     = _utxo.Select(utxo =>
            {
                var keyPair = Ed25519.GenerateKeyPairFromSecret(_secretKey);
                var hash    = _hashProvider.ComputeHashString(new
                {
                    Transaction = utxo.TransactionId,
                    utxo.Index,
                    utxo.Address
                });
                utxo.Signature = Ed25519.Sign(keyPair, hash);
                return(utxo);
            }).Select(x => new TransactionItem
            {
                TransactionId = x.TransactionId,
                Index         = x.Index,
                Address       = x.Address,
                Amount        = x.Amount,
                Signature     = x.Signature,
                Type          = TransactionDataType.Input
            }).AsList();

            // Add target receiver
            var outputIndex = 1;
            var outputs     = new List <TransactionItem>
            {
                new TransactionItem
                {
                    Index         = outputIndex++,
                    TransactionId = transactionId,
                    Amount        = _totalAmount.Value,
                    Address       = _outputAddress,
                    Type          = TransactionDataType.Output
                }
            };

            // Add change amount
            if (changeAmount > 0)
            {
                outputs.Add(new TransactionItem
                {
                    Index         = outputIndex,
                    TransactionId = transactionId,
                    Amount        = changeAmount.GetValueOrDefault(),
                    Address       = _changeAddress,
                    Type          = TransactionDataType.Output
                });
            }

            // The remaining value is the fee to be collected by the block's creator
            var transaction = new Transaction
            {
                Id   = transactionId,
                Type = _type,
                Data = new TransactionData
                {
                    Inputs  = inputs,
                    Outputs = outputs.AsList()
                }
            };

            transaction.Hash = _hashProvider.ComputeHashBytes(transaction);

            return(transaction);
        }
예제 #3
0
 public static string ToHashString(this Block block, IHashProvider hashProvider)
 {
     return(hashProvider.ComputeHashString(block));
 }
예제 #4
0
 public string ToHashString(IHashProvider provider)
 {
     return(provider.ComputeHashString(this));
 }