public IRpcMethodResult SignMessage(string address, string message) { try { var account = new AccountComponent().GetAccountById(address); if (account == null || string.IsNullOrWhiteSpace(account.PrivateKey)) { throw new CommonException(ErrorCode.Service.Account.ACCOUNT_NOT_FOUND); } ECDsa dsa = ECDsa.ImportPrivateKey(Base16.Decode(DecryptPrivateKey(account.PrivateKey))); var signResult = Base16.Encode(dsa.SingnData(Encoding.UTF8.GetBytes(message))); var result = new { signature = signResult, publicKey = account.PublicKey }; return(Ok(result)); } catch (CommonException ce) { return(Error(ce.ErrorCode, ce.Message, ce)); } catch (Exception ex) { return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex)); } }
public Account ImportAccount(string privateKeyText) { var dac = AccountDac.Default; 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; AccountDac.Default.Insert(account); } return(account); }
public static string BuildUnlockScript(string transactionHash, int outputIndex, byte[] privateKey, byte[] publicKey) { var data = new List <byte>(); data.AddRange(Base16.Decode(transactionHash)); var indexBytes = BitConverter.GetBytes(outputIndex); if (BitConverter.IsLittleEndian) { Array.Reverse(indexBytes); } data.AddRange(indexBytes); using (var dsa = ECDsa.ImportPrivateKey(privateKey)) { if (Base16.Encode(dsa.PublicKey) != Base16.Encode(publicKey)) { throw new CommonException(ErrorCode.Engine.Transaction.Verify.PRIVATE_KEY_IS_ERROR); } var signature = dsa.SingnData(data.ToArray()); return(string.Format( UNLOCK_SCRIPT_TEMPLATE, Base16.Encode(signature), Base16.Encode(dsa.PublicKey) )); } }
public bool ForgeBlock(string startId, string minerAddress, long nonce, out BlockMsg successBlock) { successBlock = null; var block = RedisManager.Current.GetDataInRedis <BlockMsg>(startId); if (block == null) { return(false); } LogHelper.Info("Forge Block 7"); //区块由矿池生成,奖励由矿池分配给矿工 block.Header.GeneratorId = minerAddress; block.Header.Nonce = nonce; block.Header.Timestamp = Time.EpochTime; var dsa = ECDsa.ImportPrivateKey(_poolPrivateKey); block.Header.BlockSignature = Base16.Encode(dsa.SingnData(Base16.Decode(block.Header.PayloadHash))); block.Header.BlockSigSize = block.Header.BlockSignature.Length; block.Header.Hash = block.Header.GetHash(); block.Header.TotalTransaction = block.Transactions.Count; var result = NodeApi.Current.ForgeBlock(block); if (result) { //关闭挖矿 PoolCenterJob.Current.StopMining(true, startId); RedisManager.Current.SaveDataToRedis(startId, block); successBlock = block; var currentTime = Time.EpochTime; var startTime = block.Header.Timestamp; if (block.Header.Height == this.currentBlockHeight) { startTime = this.currentBlockStartTime; LogHelper.Info($"block start time is {Time.GetLocalDateTime(startTime)}"); } //ConfigurationTool.GetAppSettings<PoolCenterSetting>("PoolCenterSetting").GenerateBlockDelayTime; int generateBlockDelaySeconds = ConfigCenter.ConfigPoolCenter.GenerateBlockDelayTime; if (currentTime - startTime < generateBlockDelaySeconds) { var waitTime = generateBlockDelaySeconds - (int)(currentTime - startTime); LogHelper.Info($"Block generate time {currentTime - startTime} less than {generateBlockDelaySeconds/1000} seconds, wait for a moment"); System.Threading.Thread.Sleep(waitTime); } } LogHelper.Info("ForgeBlock Result = " + result); return(result); }
/// <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); }