Esempio n. 1
0
        public Account ImportObservedAccount(string publicKeyText)
        {
            var dac = new AccountDac();

            var publicKey = Base16.Decode(publicKeyText);
            var id        = AccountIdHelper.CreateAccountAddress(publicKey);

            Account account = dac.SelectById(id);

            if (account == null)
            {
                account             = new Account();
                account.Id          = AccountIdHelper.CreateAccountAddress(publicKey);
                account.PrivateKey  = null;
                account.PublicKey   = Base16.Encode(publicKey);
                account.Balance     = 0;
                account.IsDefault   = false;
                account.WatchedOnly = true;

                dac.Insert(account);
                UtxoSet.Instance.AddAccountId(account.Id);
            }

            return(account);
        }
Esempio n. 2
0
        public Account ImportAccount(string privateKeyText)
        {
            var dac = new AccountDac();

            byte[] privateKey = Base16.Decode(privateKeyText);
            byte[] publicKey;
            using (var dsa = ECDsa.ImportPrivateKey(privateKey))
            {
                publicKey = dsa.PublicKey;
            }

            var     id      = AccountIdHelper.CreateAccountAddress(publicKey);
            Account account = dac.SelectById(id);

            if (account == null)
            {
                account             = new Account();
                account.Id          = AccountIdHelper.CreateAccountAddress(publicKey);
                account.PrivateKey  = Base16.Encode(privateKey);
                account.PublicKey   = Base16.Encode(publicKey);
                account.Balance     = 0;
                account.IsDefault   = false;
                account.WatchedOnly = false;

                dac.Insert(account);
                UtxoSet.Instance.AddAccountId(account.Id);
            }

            return(account);
        }
Esempio n. 3
0
        public void RefreshUtxoSet(string accountId)
        {
            var outputDac  = new OutputDac();
            var accountDac = new AccountDac();
            var txDac      = new TransactionDac();

            var account = accountDac.SelectById(accountId);

            if (account != null && UtxoSet.Instance != null)
            {
                var set = UtxoSet.Instance.GetUtxoSetByAccountId(accountId);

                if (set != null)
                {
                    set.Clear();

                    //load from database
                    var outputsInDB = outputDac.SelectUnspentByReceiverId(accountId);

                    foreach (var output in outputsInDB)
                    {
                        var msg = new UtxoMsg();
                        msg.AccountId       = output.ReceiverId;
                        msg.TransactionHash = output.TransactionHash;
                        msg.OutputIndex     = output.Index;
                        msg.Amount          = output.Amount;
                        msg.IsConfirmed     = true;
                        msg.IsWatchedOnly   = account.WatchedOnly;

                        var txEntity = txDac.SelectByHash(output.TransactionHash);
                        msg.BlockHash = txEntity != null ? txEntity.BlockHash : null;

                        set.Add(msg);
                    }

                    //load from transaction pool
                    var outputsInTxPool = TransactionPool.Instance.GetTransactionOutputsByAccountId(accountId);

                    foreach (var txHash in outputsInTxPool.Keys)
                    {
                        foreach (var output in outputsInTxPool[txHash])
                        {
                            var msg = new UtxoMsg();
                            msg.AccountId       = accountId;
                            msg.TransactionHash = txHash;
                            msg.OutputIndex     = output.Index;
                            msg.Amount          = output.Amount;
                            msg.IsConfirmed     = false;
                            msg.IsWatchedOnly   = account.WatchedOnly;

                            set.Add(msg);
                        }
                    }
                }
            }
        }
        public TransactionMsg CreateNewTransactionMsg(List <UtxoMsg> utxos, Dictionary <string, long> receiverIdAndValues)
        {
            var outputDac  = new OutputDac();
            var accountDac = new AccountDac();

            var transaction = new TransactionMsg();

            transaction.Timestamp = Time.EpochTime;
            transaction.Locktime  = 0;

            foreach (var utxo in utxos)
            {
                var account = accountDac.SelectById(utxo.AccountId);

                if (account == null || account.WatchedOnly)
                {
                    //TODO: throw exception;
                    return(null);
                }

                var privateKey = account.PrivateKey;
                var inputMsg   = new InputMsg();
                inputMsg.OutputTransactionHash = utxo.TransactionHash;
                inputMsg.OutputIndex           = utxo.OutputIndex;
                inputMsg.UnlockScript          = Script.BuildUnlockScript(utxo.TransactionHash, utxo.OutputIndex, Base16.Decode(privateKey), Base16.Decode(account.PublicKey));
                inputMsg.Size = inputMsg.UnlockScript.Length;

                transaction.Inputs.Add(inputMsg);
                outputDac.UpdateSpentStatus(utxo.TransactionHash, utxo.OutputIndex);
            }

            int index = 0;

            foreach (var key in receiverIdAndValues.Keys)
            {
                var value = receiverIdAndValues[key];

                var outputMsg = new OutputMsg();
                outputMsg.Index      = index;
                outputMsg.Amount     = value;
                outputMsg.LockScript = Script.BuildLockScipt(key);
                outputMsg.Size       = outputMsg.LockScript.Length;

                transaction.Outputs.Add(outputMsg);
                index++;
            }

            transaction.Hash = transaction.GetHash();
            return(transaction);
        }
Esempio n. 5
0
        //result is List<txid + "," + vout>
        public long GetAllUnconfirmedBalance()
        {
            var  accountDac  = new AccountDac();
            long totalAmount = 0;

            foreach (var item in TransactionPool.Instance.MainPool)
            {
                foreach (var output in item.Transaction.Outputs)
                {
                    var address = AccountIdHelper.CreateAccountAddressByPublicKeyHash(
                        Base16.Decode(
                            Script.GetPublicKeyHashFromLockScript(output.LockScript)));

                    if (accountDac.SelectById(address) != null)
                    {
                        totalAmount += output.Amount;
                    }
                }
            }

            return(totalAmount);
        }
Esempio n. 6
0
        public Account ImportPublicKeyAndAddress(string filePath, string salt)
        {
            Account result = null;

            string extensionName = Path.GetExtension(filePath).ToLower();

            if (extensionName != encryptExtensionName && extensionName != noEncryptExtensionName)
            {
                throw new CommonException(ErrorCode.Engine.Wallet.IO.EXTENSION_NAME_NOT_SUPPORT);
            }
            WatchAccountBackup backup = null;

            try
            {
                if (extensionName == noEncryptExtensionName)
                {
                    backup = LoadFile <WatchAccountBackup>(filePath, null);
                }
                else
                {
                    backup = LoadFile <WatchAccountBackup>(filePath, salt);
                }
                if (backup != null)
                {
                    AccountDac dac = AccountDac.Default;
                    dac.Insert(new Account {
                        Balance = 0, Id = backup.Address, IsDefault = false, PrivateKey = null, PublicKey = backup.PublicKey, Tag = "", Timestamp = Time.EpochTime, WatchedOnly = true
                    });
                    result = dac.SelectById(backup.Address);
                }
            }
            catch (Exception ex)
            {
                throw new CommonException(ErrorCode.Engine.Wallet.DB.EXECUTE_SQL_ERROR, ex);
            }
            return(result);
        }
Esempio n. 7
0
        //public List<UtxoMsg> GetAllConfirmedOutputs()
        //{
        //    return UtxoSet.Instance.GetAllUnspentOutputs();
        //}


        public List <UtxoMsg> GetAllConfirmedOutputs()
        {
            List <UtxoMsg> utxoMsgs = new List <UtxoMsg>();

            var outputDac  = new OutputDac();
            var txDac      = new TransactionDac();
            var blockDac   = new BlockDac();
            var accountDac = new AccountDac();

            var lastHeight = -1L;
            var lastBlock  = blockDac.SelectLast();

            if (lastBlock != null)
            {
                lastHeight = lastBlock.Height;
            }
            var outputs = outputDac.SelectAllUnspentOutputs();

            foreach (var output in outputs)
            {
                var msg = new UtxoMsg();
                msg.AccountId       = output.ReceiverId;
                msg.TransactionHash = output.TransactionHash;
                msg.OutputIndex     = output.Index;
                msg.Amount          = output.Amount;
                msg.IsConfirmed     = true;
                var account = accountDac.SelectById(msg.AccountId);
                msg.IsWatchedOnly = account.WatchedOnly;

                var txEntity = txDac.SelectByHash(output.TransactionHash);
                msg.BlockHash = txEntity != null ? txEntity.BlockHash : null;
                utxoMsgs.Add(msg);
            }

            return(utxoMsgs);
        }
Esempio n. 8
0
        public Account GetAccountById(string id)
        {
            var dac = new AccountDac();

            return(dac.SelectById(id));
        }
Esempio n. 9
0
        /// <summary>
        /// 创建新的区块
        /// </summary>
        /// <param name="minerName"></param>
        /// <param name="generatorId"></param>
        /// <param name="accountId"></param>
        /// <returns></returns>
        public BlockMsg CreateNewBlock(string minerName, string generatorId, string remark = null, string accountId = null)
        {
            var accountDac      = new AccountDac();
            var blockDac        = new BlockDac();
            var outputDac       = new OutputDac();
            var txDac           = new TransactionDac();
            var txPool          = TransactionPool.Instance;
            var transactionMsgs = new List <TransactionMsg>();

            long   lastBlockHeight    = -1;
            string lastBlockHash      = Base16.Encode(HashHelper.EmptyHash());
            long   lastBlockBits      = -1;
            string lastBlockGenerator = null;

            //获取最后一个区块
            var blockEntity = blockDac.SelectLast();

            if (blockEntity != null)
            {
                lastBlockHeight    = blockEntity.Height;
                lastBlockHash      = blockEntity.Hash;
                lastBlockBits      = blockEntity.Bits;
                lastBlockGenerator = blockEntity.GeneratorId;
            }

            long totalSize    = 0;
            long maxSize      = BlockSetting.MAX_BLOCK_SIZE - (1 * 1024);
            var  poolItemList = txPool.MainPool.OrderByDescending(t => t.FeeRate).ToList();
            var  index        = 0;

            while (totalSize < maxSize && index < poolItemList.Count)
            {
                var tx = poolItemList[index].Transaction;

                if (tx != null && transactionMsgs.Where(t => t.Hash == tx.Hash).Count() == 0)
                {
                    if (txDac.SelectByHash(tx.Hash) == null)
                    {
                        transactionMsgs.Add(tx);
                        totalSize += tx.Size;
                    }
                    else
                    {
                        txPool.RemoveTransaction(tx.Hash);
                    }
                }
                else
                {
                    break;
                }

                index++;
            }


            var minerAccount = accountDac.SelectDefaultAccount();

            if (accountId != null)
            {
                var account = accountDac.SelectById(accountId);

                if (account != null && !string.IsNullOrWhiteSpace(account.PrivateKey))
                {
                    minerAccount = account;
                }
            }

            var minerAccountId = minerAccount.Id;

            BlockMsg       newBlockMsg = new BlockMsg();
            BlockHeaderMsg headerMsg   = new BlockHeaderMsg();

            headerMsg.Hash              = Base16.Encode(HashHelper.EmptyHash());
            headerMsg.GeneratorId       = generatorId;
            newBlockMsg.Header          = headerMsg;
            headerMsg.Height            = lastBlockHeight + 1;
            headerMsg.PreviousBlockHash = lastBlockHash;

            if (headerMsg.Height == 0)
            {
                minerAccountId = BlockSetting.GenesisBlockReceiver;
                remark         = BlockSetting.GenesisBlockRemark;
            }

            long totalAmount = 0;
            long totalFee    = 0;

            foreach (var tx in transactionMsgs)
            {
                long totalInputsAmount = 0L;
                long totalOutputAmount = 0L;

                foreach (var input in tx.Inputs)
                {
                    var utxo = outputDac.SelectByHashAndIndex(input.OutputTransactionHash, input.OutputIndex);

                    if (utxo != null)
                    {
                        totalInputsAmount += utxo.Amount;
                    }
                }

                foreach (var output in tx.Outputs)
                {
                    totalOutputAmount += output.Amount;
                }

                totalAmount += totalOutputAmount;
                totalFee    += (totalInputsAmount - totalOutputAmount);
            }

            //var work = new POW(headerMsg.Height);
            BlockMsg prevBlockMsg     = null;
            BlockMsg prevStepBlockMsg = null;

            if (blockEntity != null)
            {
                prevBlockMsg = this.convertEntityToBlockMsg(blockEntity);
            }

            if (headerMsg.Height >= POC.DIFFIUCLTY_ADJUST_STEP)
            {
                prevStepBlockMsg = this.GetBlockMsgByHeight(headerMsg.Height - POC.DIFFIUCLTY_ADJUST_STEP - 1);
            }

            var newBlockReward = POC.GetNewBlockReward(headerMsg.Height);

            headerMsg.Bits             = POC.CalculateBaseTarget(headerMsg.Height, prevBlockMsg, prevStepBlockMsg);
            headerMsg.TotalTransaction = transactionMsgs.Count + 1;

            var coinbaseTxMsg = new TransactionMsg();

            coinbaseTxMsg.Timestamp = Time.EpochTime;
            coinbaseTxMsg.Locktime  = 0;

            var coinbaseInputMsg = new InputMsg();

            coinbaseTxMsg.Inputs.Add(coinbaseInputMsg);
            coinbaseInputMsg.OutputIndex           = 0;
            coinbaseInputMsg.OutputTransactionHash = Base16.Encode(HashHelper.EmptyHash());
            coinbaseInputMsg.UnlockScript          = Script.BuildMinerScript(minerName, remark);
            coinbaseInputMsg.Size = coinbaseInputMsg.UnlockScript.Length;

            var coinbaseOutputMsg = new OutputMsg();

            coinbaseTxMsg.Outputs.Add(coinbaseOutputMsg);
            coinbaseOutputMsg.Amount     = newBlockReward + totalFee;
            coinbaseOutputMsg.LockScript = Script.BuildLockScipt(minerAccountId);
            coinbaseOutputMsg.Size       = coinbaseOutputMsg.LockScript.Length;
            coinbaseOutputMsg.Index      = 0;

            coinbaseTxMsg.Hash = coinbaseTxMsg.GetHash();

            newBlockMsg.Transactions.Insert(0, coinbaseTxMsg);

            foreach (var tx in transactionMsgs)
            {
                newBlockMsg.Transactions.Add(tx);
            }

            headerMsg.PayloadHash = newBlockMsg.GetPayloadHash();
            var dsa        = ECDsa.ImportPrivateKey(Base16.Decode(minerAccount.PrivateKey));
            var signResult = dsa.SingnData(Base16.Decode(headerMsg.PayloadHash));

            headerMsg.BlockSignature   = Base16.Encode(signResult);
            headerMsg.BlockSigSize     = headerMsg.BlockSignature.Length;
            headerMsg.TotalTransaction = newBlockMsg.Transactions.Count;
            return(newBlockMsg);
        }
Esempio n. 10
0
        public TransactionMsg CreateNewTransactionMsg(string senderAccountId, Dictionary <string, long> receiverIdAndValues, long fee)
        {
            var outputDac  = new OutputDac();
            var accountDac = new AccountDac();

            var account = accountDac.SelectById(senderAccountId);

            if (account == null || account.WatchedOnly)
            {
                //TODO: throw exception;
                return(null);
            }

            var  balance     = UtxoSet.Instance.GetAccountBlanace(senderAccountId, true);
            long totalOutput = fee;
            long totalInput  = 0;

            foreach (var key in receiverIdAndValues.Keys)
            {
                totalOutput += receiverIdAndValues[key];
            }

            if (totalOutput > balance)
            {
                //TODO: throw exception
                return(null);
            }

            var transaction = new TransactionMsg();

            transaction.Timestamp = Time.EpochTime;
            transaction.Locktime  = 0;

            var outputs = outputDac.SelectUnspentByReceiverId(senderAccountId);

            foreach (var output in outputs)
            {
                var inputMsg = new InputMsg();
                inputMsg.OutputTransactionHash = output.TransactionHash;
                inputMsg.OutputIndex           = output.Index;
                inputMsg.UnlockScript          = Script.BuildUnlockScript(output.TransactionHash, output.Index, Base16.Decode(account.PrivateKey), Base16.Decode(account.PublicKey));
                inputMsg.Size = inputMsg.UnlockScript.Length;

                transaction.Inputs.Add(inputMsg);
                outputDac.UpdateSpentStatus(output.TransactionHash, output.Index);

                totalInput += output.Amount;
                if (totalInput >= totalOutput)
                {
                    break;
                }
            }

            int index = 0;

            foreach (var key in receiverIdAndValues.Keys)
            {
                var value = receiverIdAndValues[key];

                var outputMsg = new OutputMsg();
                outputMsg.Index      = index;
                outputMsg.Amount     = value;
                outputMsg.LockScript = Script.BuildLockScipt(key);
                outputMsg.Size       = outputMsg.LockScript.Length;

                transaction.Outputs.Add(outputMsg);
                index++;
            }

            if (totalInput > totalOutput)
            {
                var value = totalInput - totalOutput;

                var outputMsg = new OutputMsg();
                outputMsg.Index      = index;
                outputMsg.Amount     = value;
                outputMsg.LockScript = Script.BuildLockScipt(senderAccountId);
                outputMsg.Size       = outputMsg.LockScript.Length;

                transaction.Outputs.Add(outputMsg);
                index++;
            }

            transaction.Hash = transaction.GetHash();

            return(transaction);
        }
Esempio n. 11
0
        public BlockMsg CreateNewBlock(string minerName, string accountId = null)
        {
            var accountDac      = new AccountDac();
            var blockDac        = new BlockDac();
            var outputDac       = new OutputDac();
            var txDac           = new TransactionDac();
            var txPool          = TransactionPool.Instance;
            var transactionMsgs = new List <TransactionMsg>();

            long   lastBlockHeight = -1;
            string lastBlockHash   = Base16.Encode(HashHelper.EmptyHash());
            long   lastBlockBits   = -1;

            var blockEntity = blockDac.SelectLast();

            if (blockEntity != null)
            {
                lastBlockHeight = blockEntity.Height;
                lastBlockHash   = blockEntity.Hash;
                lastBlockBits   = blockEntity.Bits;
            }

            long totalSize    = 0;
            long maxSize      = BlockSetting.MAX_BLOCK_SIZE - (500 * 1024);
            var  poolItemList = txPool.MainPool.OrderByDescending(t => t.FeeRate).ToList();
            var  index        = 0;

            while (totalSize < maxSize && index < poolItemList.Count)
            {
                var tx = poolItemList[index].Transaction;

                if (tx != null && transactionMsgs.Where(t => t.Hash == tx.Hash).Count() == 0)
                {
                    if (txDac.SelectByHash(tx.Hash) == null)
                    {
                        transactionMsgs.Add(tx);
                        totalSize += tx.Size;
                    }
                    else
                    {
                        txPool.RemoveTransaction(tx.Hash);
                    }
                }
                else
                {
                    break;
                }

                index++;
            }


            var minerAccount = accountDac.SelectDefaultAccount();

            if (accountId != null)
            {
                var account = accountDac.SelectById(accountId);

                if (account != null && !string.IsNullOrWhiteSpace(account.PrivateKey))
                {
                    minerAccount = account;
                }
            }

            BlockMsg       newBlockMsg = new BlockMsg();
            BlockHeaderMsg headerMsg   = new BlockHeaderMsg();

            newBlockMsg.Header          = headerMsg;
            headerMsg.Height            = lastBlockHeight + 1;
            headerMsg.PreviousBlockHash = lastBlockHash;


            long totalAmount = 0;
            long totalFee    = 0;

            foreach (var tx in transactionMsgs)
            {
                long totalInputsAmount = 0L;
                long totalOutputAmount = 0L;

                foreach (var input in tx.Inputs)
                {
                    var utxo = outputDac.SelectByHashAndIndex(input.OutputTransactionHash, input.OutputIndex);

                    if (utxo != null)
                    {
                        totalInputsAmount += utxo.Amount;
                    }
                }

                foreach (var output in tx.Outputs)
                {
                    totalOutputAmount += output.Amount;
                }

                totalAmount += totalOutputAmount;
                totalFee    += (totalInputsAmount - totalOutputAmount);
            }

            var      work = new POW(headerMsg.Height);
            BlockMsg previous4032Block = null;

            if (headerMsg.Height > POW.DiffiucltyAdjustStep)
            {
                previous4032Block = this.GetBlockMsgByHeight(headerMsg.Height - POW.DiffiucltyAdjustStep);
            }

            var newBlockReward = work.GetNewBlockReward();

            headerMsg.Bits             = work.CalculateNextWorkTarget(lastBlockHeight, lastBlockBits, previous4032Block);
            headerMsg.TotalTransaction = transactionMsgs.Count + 1;

            var coinbaseTxMsg = new TransactionMsg();

            coinbaseTxMsg.Timestamp = Time.EpochTime;
            coinbaseTxMsg.Locktime  = 0;

            var coinbaseInputMsg = new InputMsg();

            coinbaseTxMsg.Inputs.Add(coinbaseInputMsg);
            coinbaseInputMsg.OutputIndex           = 0;
            coinbaseInputMsg.OutputTransactionHash = Base16.Encode(HashHelper.EmptyHash());
            coinbaseInputMsg.UnlockScript          = Script.BuildMinerScript(minerName);
            coinbaseInputMsg.Size = coinbaseInputMsg.UnlockScript.Length;

            var coinbaseOutputMsg = new OutputMsg();

            coinbaseTxMsg.Outputs.Add(coinbaseOutputMsg);
            coinbaseOutputMsg.Amount     = newBlockReward + totalFee;
            coinbaseOutputMsg.LockScript = Script.BuildLockScipt(minerAccount.Id);
            coinbaseOutputMsg.Size       = coinbaseOutputMsg.LockScript.Length;
            coinbaseOutputMsg.Index      = 0;

            coinbaseTxMsg.Hash = coinbaseTxMsg.GetHash();

            newBlockMsg.Transactions.Insert(0, coinbaseTxMsg);

            foreach (var tx in transactionMsgs)
            {
                newBlockMsg.Transactions.Add(tx);
            }

            return(newBlockMsg);
        }