public NewTransactionIncludeResult Validate(NodeIndex nodeIndex, OngoingBlock ongoingBlock, Transaction transaction) { if (!nodeIndex.IsEmpty && nodeIndex.Orders.AllOrders.ContainsKey(transaction.Signature)) { throw new TransactionDeclinedException("Already processed."); } if (ongoingBlock.Transactions.Any(t => t.Signature == transaction.Signature)) { throw new TransactionDeclinedException("Already received."); } if (ongoingBlock.Transactions.Any(t => t.User == transaction.User)) { throw new TransactionDeclinedException("Not alowed to request many transaction for one block."); } UserIndex existUser; if (!nodeIndex.IsEmpty && nodeIndex.Users.AllUsers.TryGetValue(transaction.User, out existUser)) { //check that user does not spam transactions. Only 1 transaction per block. //This requirement simplify transaction consistency validation if (existUser.LastTransaction.Signature != transaction.Previous) { throw new TransactionDeclinedException("Wrong user transactions order."); } } else { existUser = null; } if (transaction.Message is OrderRequested) { return(_orderRequestedValidator.Validate(nodeIndex, existUser, ongoingBlock, (OrderRequested)transaction.Message)); } else { if (transaction.Message is OrdersAssigned) { return(_ordersAssignedValidator.Validate(nodeIndex, existUser, ongoingBlock, (OrdersAssigned)transaction.Message)); } else { throw new TransactionDeclinedException("Unkown user message type."); } } }
public NewTransactionIncludeResult Calculate(NodeIndex nodeIndex, OngoingBlock ongoingBlock, OrdersAssigned newOrder) { var newPrize = _transactionPrizeCalculator.GetPrize(nodeIndex, newOrder); var usedOrders = new HashSet <HashValue>(newOrder.Orders); var toRemoveTransactionsDic = new Dictionary <HashValue, Transaction>(); foreach (var ongoingTransaction in ongoingBlock.Transactions) { if (!(ongoingTransaction.Message is OrdersAssigned)) { continue; } var ongoingOrders = ((OrdersAssigned)ongoingTransaction.Message).Orders; foreach (var ongoingOrder in ongoingOrders) { if (usedOrders.Contains(ongoingOrder)) { toRemoveTransactionsDic[ongoingTransaction.Signature] = ongoingTransaction; break; } } } double lostPrize = 0; foreach (var t in toRemoveTransactionsDic.Values) { lostPrize += _transactionPrizeCalculator.GetPrize(nodeIndex, (OrdersAssigned)t.Message); } if (newPrize <= lostPrize) { return(NewTransactionIncludeResult.None); } return(new NewTransactionIncludeResult(toRemoveTransactionsDic.Values.ToArray())); }
public NewTransactionIncludeResult Validate(NodeIndex nodeIndex, UserIndex userIndex, OngoingBlock ongoingBlock, OrdersAssigned message) { if (message.Fee < 0 || message.Fee > 1) { throw new TransactionDeclinedException("Invalid Fee."); } if (message.Orders.Count == 0) { throw new TransactionDeclinedException("Empty orders."); } return(_bestPrizeTransactionsSelector.Calculate(nodeIndex, ongoingBlock, message)); }
public NewTransactionIncludeResult Validate(NodeIndex nodeIndex, UserIndex userIndex, OngoingBlock ongoingBlock, OrderRequested message) { var order = message.Order; if (order.Payment <= 0) { throw new TransactionDeclinedException("Invalid order Payment."); } var validator = _validators[order.OrderType]; validator.Validate(nodeIndex, userIndex, order); return(NewTransactionIncludeResult.Include); }