/** * Handles each epoch by receiving an unordered array of proposed transactions, checking each * transaction for correctness, returning a mutually valid array of accepted transactions, and * updating the current UTXO pool as appropriate. */ public Transaction[] handleTxs(List <Transaction> possibleTxs) { // IMPLEMENT THIS HashSet <Transaction> txVis = new HashSet <Transaction>(); //fixed point algorithm,iter untill no new transaction is valid while (true) { bool updated = false; foreach (Transaction tx in possibleTxs) { if (txVis.Contains(tx)) { continue; } if (isValidTx(tx)) { txVis.Add(tx); updated = true; //add unspent coin for (uint i = 0; i < tx.numOutputs(); ++i) { UTXO utxo = new UTXO(tx.getHash(), i); CommitedUtxoPool.addUTXO(utxo, tx.getOutput((int)i)); } //delete spent coin for (int i = 0; i < tx.numInputs(); ++i) { Input input = tx.getInput(i); UTXO utxo = new UTXO(input.PreTxHash, (uint)input.OutputIndex); CommitedUtxoPool.removeUTXO(utxo); } } } if (!updated) { break; } } ; Transaction[] ret = new Transaction[txVis.Count()]; int idx = 0; foreach (Transaction tx in txVis) { ret[idx++] = tx; } return(ret); }
/// <summary> /// 根据block信息更新UTXO pool,同时返回该block生成的utxo list,用来提示该block收到了多少钱 /// </summary> /// <param name="block"></param> /// <returns>just for update key corresponding value</returns> public UTXOPool BlockData2UTXOPool(bool bCommitedPool, Block block) { LogHelper.WriteMethodLog(true); LogHelper.WriteInfoLog("bCommitedPool: " + bCommitedPool.ToString()); UTXOPool utxopoll = new UTXOPool(); if (bCommitedPool) { utxopoll = this.CommitedUtxoPool; } else { utxopoll = this.UnCommitedUtxoPool; } UTXOPool sigleBlockPool = new UTXOPool(); foreach (Transaction eTransaction in block.listTransactions) { foreach (Input eInput in eTransaction.listInputs) { UTXO utxo = this.input2UTXO(eInput); if (utxopoll.contains(utxo)) { utxopoll.removeUTXO(utxo); } else { // 初始化时由于leveldb 树形结构第一个可能创世块,所以先记下来在后面再remove if (utxo.getTxHash() != ConstHelper.BC_BaseCoinInputTxHash) { tempUTXOList.Add(utxo); } } } for (int i = 0; i < eTransaction.listOutputs.Count; i++) { // hash is transaction hash UTXO utxo1 = new UTXO(eTransaction.getHash(), (uint)i); utxopoll.addUTXO(utxo1, eTransaction.listOutputs[i]); sigleBlockPool.addUTXO(utxo1, eTransaction.listOutputs[i]); } } LogHelper.WriteMethodLog(false); return(sigleBlockPool); }
public string handleTxs(Transaction tx) { try { string sRet = ConstHelper.BC_OK; if (isValidTx(tx)) { //add unspent coin for (uint i = 0; i < tx.numOutputs(); ++i) { UTXO utxo = new UTXO(tx.getHash(), i); UnCommitedUtxoPool.addUTXO(utxo, tx.getOutput((int)i)); LogHelper.WriteInfoLog(string.Format("Add utxo to uncommited pool, utxoHash:{0}", utxo.utoxHashCode())); } //delete spent coin for (int i = 0; i < tx.numInputs(); ++i) { Input input = tx.getInput(i); UTXO utxo = new UTXO(input.PreTxHash, (uint)input.OutputIndex); CommitedUtxoPool.removeUTXO(utxo); LogHelper.WriteInfoLog(string.Format("Remove utxo from commited pool, utxoHash:{0}", utxo.utoxHashCode())); } } else { sRet = "invalid transaction"; } LogHelper.WriteInfoLog("handleTxs result:" + sRet); return(sRet); } catch (Exception ex) { LogHelper.WriteErrorLog(ex.Message); return("HandleTxs catch an exception "); } }