lib/zold/patch.rb in zold-0.13.32 vs lib/zold/patch.rb in zold-0.13.33

- old
+ new

@@ -29,55 +29,73 @@ # Copyright:: Copyright (c) 2018 Yegor Bugayenko # License:: MIT module Zold # A patch class Patch - def initialize(log: Log::Quiet.new) + def initialize(wallets, log: Log::Quiet.new) + raise 'Wallets can\'t be nil' if wallets.nil? + raise 'Wallets must be of type Wallets' unless wallets.is_a?(Wallets) + @wallets = wallets + @txns = [] @log = log end def to_s - return 'empty' if @id.nil? + return 'empty' if @txns.empty? "#{@txns.count} txns" end - def join(wallet) + def join(wallet, baseline = true) if @id.nil? @id = wallet.id @key = wallet.key - @txns = wallet.txns - @log.debug("The baseline: #{@txns.count} transactions, the balance is #{wallet.balance}") + if baseline + @txns = wallet.txns + @log.debug("The baseline: #{@txns.count} transactions, the balance is #{wallet.balance}") + else + @log.debug("The baseline of #{@txns.count} transactions ignored") + end @network = wallet.network end if wallet.network != @network raise "The wallet is from a different network '#{wallet.network}', ours is '#{@network}'" end raise 'Public key mismatch' if wallet.key != @key raise "Wallet ID mismatch: #{@id} != #{wallet.id}" if wallet.id != @id - negative = @txns.select { |t| t.amount.negative? } - max = negative.empty? ? 0 : negative.max_by(&:id).id + max = @txns.select { |t| t.amount.negative? }.map(&:id).max.to_i wallet.txns.each do |txn| next if @txns.find { |t| t == txn } if txn.amount.negative? if txn.id <= max - @log.debug("Transaction ID is less than max #{max}: #{txn.to_text}") + @log.error("Transaction ID is less than max #{max}: #{txn.to_text}") next end if @txns.find { |t| t.id == txn.id } - @log.debug("Transaction ##{txn.id} already exists: #{txn.to_text}") + @log.error("Transaction ##{txn.id} already exists: #{txn.to_text}") next end if !@txns.empty? && @txns.map(&:amount).inject(&:+) < txn.amount @log.error("Transaction ##{txn.id} attempts to make the balance negative: #{txn.to_text}") next end unless Signature.new.valid?(@key, wallet.id, txn) @log.error("Invalid RSA signature at transaction ##{txn.id} of #{wallet.id}: #{txn.to_text}") next end - elsif !txn.sign.nil? && !txn.sign.empty? - @log.error("RSA signature is redundant at ##{txn.id} of #{wallet.id}: #{txn.to_text}") - next + else + if !txn.sign.nil? && !txn.sign.empty? + @log.error("RSA signature is redundant at ##{txn.id} of #{wallet.id}: #{txn.to_text}") + next + end + payer = @wallets.find(txn.bnf) + unless payer.exists? + @log.error("Paying wallet #{wallet.id} is absent at ##{txn.id}: #{txn.to_text}") + next + end + unless payer.has?(txn.id, wallet.id) + @log.error("Paying wallet #{wallet.id} doesn't have transaction ##{txn.id}: #{txn.to_text}") + next + end end @log.debug("Merged on top: #{txn.to_text}") @txns << txn end end