public TxSignature AddSignature(TxSignature signature) { TxSignature res = GetSignature(signature.TxInputId, signature.TeammateId); if (res != null) { return(res); } return(Add <TxSignature>(signature)); }
private bool ServerUpdatesToLocalDb() { Key key = GetUser().BitcoinPrivateKey; long since = _connection.LastUpdated.Ticks; var txsToUpdate = _txRepo.GetTxsNeedServerUpdate(); var txSignatures = _txRepo.GetTxsSignaturesNeedServerUpdate(); GetUpdatesResultData serverResponse = _server.GetUpdates(key, since, txsToUpdate.Where(x => x.Teammate.Team.IsInNormalState), txSignatures); if (null == serverResponse) { // todo: log record return(false); } txsToUpdate.ForEach(x => { x.NeedUpdateServer = false; _txRepo.Update(x); }); txSignatures.ForEach(x => { x.NeedUpdateServer = false; _txRepo.Update(x); }); serverResponse.Teams.ForEach(team => { var existingTeam = _teamRepo.Get(team.Id); if (existingTeam == null) { team.PayToAddressOkAge = 14; team.AutoApprovalMyGoodAddress = 3; team.AutoApprovalMyNewAddress = 7; team.AutoApprovalCosignGoodAddress = 3; team.AutoApprovalCosignNewAddress = 7; existingTeam = _teamRepo.Add(team); } else { // Can change Name if (existingTeam.Name != team.Name) { existingTeam.Name = team.Name; _teamRepo.Update(existingTeam); } } }); serverResponse.Teammates.ForEach(teammate => { var existingTeammate = _teammateRepo.Get(teammate.Id); bool okToInsertOrUpdate = true; if (existingTeammate != null) { if (existingTeammate.PublicKey != null && teammate.PublicKey != existingTeammate.PublicKey || teammate.FBName != existingTeammate.FBName || teammate.TeamId != existingTeammate.TeamId) { okToInsertOrUpdate = false; // we don't allow to change basic info } } if (okToInsertOrUpdate) { _teammateRepo.InsertOrUpdateDetached(teammate); } }); serverResponse.PayTos.ForEach(payTo => { var existingPayTo = _payToRepo.Get(payTo.TeammateId, payTo.Address); if (existingPayTo == null) { payTo.KnownSince = DateTime.UtcNow; existingPayTo = _payToRepo.Add(payTo); } if (existingPayTo.IsDefault) { _payToRepo.GetForTeammate(existingPayTo.TeammateId).ForEach(x => { if (x.Address != existingPayTo.Address) { x.IsDefault = false; _payToRepo.Update(x); } }); } }); serverResponse.BTCAddresses.ForEach(address => { if (address.Address != null && _addressRepo.Get(address.Address) == null) { if (address.Status == UserAddressStatus.Previous) { address.Status = UserAddressStatus.ServerPrevious; } else if (address.Status == UserAddressStatus.Current) { address.Status = UserAddressStatus.ServerCurrent; } else if (address.Status == UserAddressStatus.Next) { address.Status = UserAddressStatus.ServerNext; } _addressRepo.Add(address); } }); serverResponse.Cosigners.ForEach(cosigner => { if (cosigner.AddressId != null) { if (_addressRepo.Get(cosigner.AddressId) == null) // can't add cosigners to existing addresses { _cosignerRepo.Add(cosigner); } } }); // Rules for setting new current address // ok to set first address // ok to change to next address if: // -- no funds on existing current address // -- or a real Tx from current to next occurred serverResponse.Txs.ForEach(tx => { var existingTx = _txRepo.Get(tx.Id); if (existingTx == null) { tx.ReceivedTime = DateTime.UtcNow; tx.UpdateTime = DateTime.UtcNow; tx.Resolution = TxClientResolution.None; tx.ClientResolutionTime = null; tx.NeedUpdateServer = false; _txRepo.Add(tx); } else { existingTx.State = tx.State; existingTx.UpdateTime = DateTime.UtcNow; existingTx.ResolutionTime = tx.ResolutionTime; existingTx.ProcessedTime = tx.ProcessedTime; _txRepo.Update(existingTx); } }); foreach (var txInput in serverResponse.TxInputs) { if (_txRepo.GetInput(txInput.Id) != null) { continue; // can't change inputs } var tx = _txRepo.Get(txInput.TxId); if (tx == null) { tx = serverResponse.Txs.FirstOrDefault(x => x.Id == txInput.TxId); } if (tx == null) { continue; // malformed TX, todo: add log record } _txRepo.AddInput(txInput); } foreach (var txOutput in serverResponse.TxOutputs) { var tx = _txRepo.Get(txOutput.TxId); if (tx != null) { continue; // can't add outputs to existing txs } tx = serverResponse.Txs.FirstOrDefault(x => x.Id == txOutput.TxId); if (tx == null) { continue; // malformed TX, todo: add log record } _txRepo.AddOutput(txOutput); } foreach (var txSignatureInfo in serverResponse.TxSignatures) { if (_txRepo.GetSignature(txSignatureInfo.TxInputId, txSignatureInfo.TeammateId) != null) { continue; // can't change signatures } var txInput = _txRepo.GetInput(txSignatureInfo.TxInputId); if (txInput == null) { txInput = serverResponse.TxInputs.FirstOrDefault(x => x.Id == txSignatureInfo.TxInputId); } if (txInput == null) { continue; // malformed TX, todo: add log record } var txSignature = new TxSignature() { TxInputId = txSignatureInfo.TxInputId, TeammateId = txSignatureInfo.TeammateId, Signature = Convert.FromBase64String(txSignatureInfo.Signature), NeedUpdateServer = false }; _txRepo.AddSignature(txSignature); } _context.SaveChanges(); // Check outputs foreach (var arrivingTx in serverResponse.Txs) { var tx = _txRepo.Get(arrivingTx.Id); bool isWalletMove = (tx.Kind == TxKind.MoveToNextWallet || tx.Kind == TxKind.SaveFromPrevWallet); // Outputs are required unless it's a wallet update if (!isWalletMove && tx.Outputs == null) { ChangeTxResolution(tx, TxClientResolution.ErrorBadRequest); continue; } // AmountBTC sum must match total unless it's a wallet update if (!isWalletMove && Math.Abs(tx.Outputs.Sum(x => x.AmountBTC) - tx.AmountBTC.Value) > 0.000001M) { ChangeTxResolution(tx, TxClientResolution.ErrorBadRequest); continue; } if (tx.Resolution == TxClientResolution.None) { ChangeTxResolution(tx, TxClientResolution.Received); } } _context.SaveChanges(); // Check addresses serverResponse.BTCAddresses.ForEach(address => { var addressSaved = _addressRepo.Get(address.Address); if (addressSaved != null) { if (SignHelper.GenerateStringAddress(addressSaved) != addressSaved.Address) { addressSaved.Status = UserAddressStatus.Invalid; _addressRepo.Update(addressSaved); } } }); // process inputs // verify amounts if inputs are set _connection.LastUpdated = new DateTime(serverResponse.LastUpdated, DateTimeKind.Utc); _connectionRepo.Update(_connection); _context.SaveChanges(); return(true); }
public TxSignature AddSignature(TxSignature signature) { return(_txRepo.AddSignature(signature)); }
public void Update(TxSignature signature) { Update <TxSignature>(signature); }