exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

auditor-report.tex.j2 (50491B)


      1 % This file is part of TALER
      2 % Copyright (C) 2016--2023 Taler Systems SA
      3 %
      4 % TALER is free software; you can redistribute it and/or modify it under the
      5 % terms of the GNU Affero General Public License as published by the Free Software
      6 % Foundation; either version 3, or (at your option) any later version.
      7 %
      8 % TALER is distributed in the hope that it will be useful, but WITHOUT ANY
      9 % WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     10 % A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.
     11 %
     12 % You should have received a copy of the GNU Affero General Public License along with
     13 % TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     14 %
     15 %
     16 % With respect to this file, our interpretation of the license is
     17 % that publishing an audit report (i.e. in TeX or PDF) requires
     18 % publishing the corresponding j2 template sources under AGPL, and
     19 % linking to them from the report. (This file _is_ source code,
     20 % the generated PDF is the service under definition of the AGPL.)
     21 %
     22 %
     23 % NOTE WELL:
     24 %
     25 % When modifying this document, please verify that the output
     26 % still looks good. For this, we have noted which testcases
     27 % trigger the respective table being generated using comments
     28 % of the form:
     29 %
     30 % "Table generation tested by testcase #XX in test-auditor.sh"
     31 %
     32 % Thus, whenever modifying such a table, please verify that the
     33 % output still looks OK by manually inspecting the generated
     34 % PDF from running
     35 %
     36 % $ test-auditor.sh XX
     37 %
     38 % in the src/auditor/ directory.
     39 
     40 \documentclass{article} % {acmart}
     41 \usepackage{url}
     42 \usepackage[T1]{fontenc}
     43 \usepackage[utf8]{inputenc}
     44 \usepackage{multirow}
     45 \usepackage{longtable}
     46 \usepackage[breakall]{truncate}
     47 
     48 \begin{document}
     49 
     50 \title{Taler Auditor Report}
     51 
     52 % You must also credit the original author.
     53 \author{Christian Grothoff}
     54 \maketitle
     55 
     56 % If you update this template, complying with the license requires
     57 % stating the license and publishing the J2 source and linking to it
     58 % from the generated PDF.  So if you change this outside of the Taler
     59 % Git repository, you must update this link (and the link must remain
     60 % available to the receiver of the result from the generated TeX, PDF
     61 % or other format).
     62 
     63 This report is based on a template licensed under the Affero General Public
     64 License, either version 3, or (at your option) any later version.
     65 The source code for the template is available at \url{https://git.taler.net/}.
     66 
     67 The report was generated by the auditors at the following times:
     68 
     69 \begin{table}[h!]
     70 \begin{center}
     71 \begin{tabular}{l|r|r}
     72   Auditor                 & Start    & End \\ \hline \hline
     73   Aggregation             & {{ aggregation.auditor_start_time }} & {{ aggregation.auditor_end_time }} \\ \hline
     74   Coins                   & {{ coins.auditor_start_time }} & {{ coins.auditor_end_time }} \\ \hline
     75   Deposits                & {{ deposits.auditor_start_time }} & {{ deposits.auditor_end_time }} \\ \hline
     76   Reserves                & {{ reserves.auditor_start_time }} & {{ reserves.auditor_end_time }} \\ \hline
     77   Wire                    & {{ wire.wire_auditor_start_time }} & {{ wire.wire_auditor_end_time }} \\
     78 \end{tabular}
     79 \end{center}
     80 \end{table}
     81 
     82 In that time, the auditors processed the following table ranges:
     83 \begin{table}[h!]
     84 \begin{center}
     85 \begin{tabular}{l|r|r}
     86   Table                   & Start    & End \\ \hline \hline
     87   Reserves Incoming       & {{ reserves.start_ppr_reserve_in_serial_id }}
     88                           & {{ reserves.end_ppr_reserve_in_serial_id }} \\ \hline
     89   Reserves Out (withdraw) & {{ reserves.start_ppr_reserve_out_serial_id }}
     90                           & {{ reserves.end_ppr_reserve_out_serial_id }} \\ \hline
     91   Reserves Recoup         & {{ reserves.start_ppr_reserve_recoup_serial_id }}
     92                           & {{ reserves.end_ppr_reserve_recoup_serial_id }} \\ \hline
     93   Reserves Close          & {{ reserves.start_ppr_reserve_close_serial_id }}
     94                           & {{ reserves.end_ppr_reserve_close_serial_id }} \\ \hline
     95   Aggregation             & {{ aggregation.start_ppa_wire_out_serial_id }}
     96                           & {{ aggregation.end_ppa_wire_out_serial_id }} \\ \hline
     97   Aggregation (wire)      & {{ wire.start_pp_last_aggregation_serial_id }}
     98                           & {{ wire.end_pp_last_aggregation_serial_id }} \\ \hline
     99   Deposits (wire)         & {{ wire.start_pp_last_batch_deposit_id }}
    100                           & {{ wire.end_pp_last_batch_deposit_id }} \\ \hline
    101   Reserves Close (wire)   & {{ wire.start_pp_reserve_close_id }}
    102                           & {{ wire.end_pp_reserve_close_id }} \\ \hline
    103   Coin withdraw           & {{ coins.start_ppc_withdraw_serial_id }}
    104                           & {{ coins.end_ppc_withdraw_serial_id }} \\ \hline
    105   Coin deposit            & {{ coins.start_ppc_deposit_serial_id }}
    106                           & {{ coins.end_ppc_deposit_serial_id }} \\ \hline
    107   Coin melt               & {{ coins.start_ppc_melt_serial_id }}
    108                           & {{ coins.end_ppc_melt_serial_id }} \\ \hline
    109   Coin refund             & {{ coins.start_ppc_refund_serial_id }}
    110                           & {{ coins.end_ppc_refund_serial_id }} \\ \hline
    111   Coin recoup             & {{ coins.start_ppc_recoup_serial_id }}
    112                           & {{ coins.end_ppc_recoup_serial_id }} \\ \hline
    113   Coin recoup refresh     & {{ coins.start_ppc_recoup_refresh_serial_id }}
    114                           & {{ coins.end_ppc_recoup_refresh_serial_id }} \\
    115 \end{tabular}
    116 \end{center}
    117 \caption{Serial number ranges of the tables processed by the audit.}
    118 \label{table:auditor_range}
    119 \end{table}
    120 
    121 {% if wire.account_progress|length() == 0 %}
    122 In that time, the wire auditor processed NO accounts at all.
    123 {% else %}
    124 In that time, the wire auditor processed the following table ranges:
    125 \begin{center}
    126 \begin{longtable}{l|c|r|r}
    127   Account & Table         & Start    & End \\ \hline
    128 \endfirsthead
    129   Account & Table         & Start    & End \\ \hline
    130 \endhead
    131 \endfoot
    132   \caption{Range of account data processed by the wire auditor.}
    133   \label{table:account_range}
    134 \endlastfoot
    135 {% for item in wire.account_progress %}
    136   \hline
    137   {{ item.account }} &
    138   Reserves Incoming       & {{ item.start_reserve_in }}
    139                           & {{ item.end_reserve_in }} \\ \hline
    140   &
    141   Outgoing wire transfers & {{ item.start_wire_out }}
    142                           & {{ item.end_wire_out }} \\
    143 {% endfor %}
    144 \end{longtable}
    145 {% endif %}
    146 \end{center}
    147 
    148 The total credits to the exchange processed in
    149 this audit run was {\bf {{ wire.total_wire_in }}}.
    150 The total debits initiated by the exchange processed in
    151 this audit run was {\bf {{ wire.total_wire_out }}}.
    152 
    153 \section{Operations}
    154 
    155 The balance of the escrow account should
    156 be {\bf {{ coins.total_escrow_balance }}} (coins)
    157 plus {\bf {{ reserves.total_escrow_balance }}} (reserves).
    158 
    159 \noindent
    160 This should match the final balance computed from
    161 ingoing and outgoing wire transfers, which is
    162 {\bf {{ wire.final_balance}} }.
    163 
    164 \noindent
    165 A total of {\bf {{ wire.total_drained}} } in profits
    166 were transferred (over the lifetime of the exchange)
    167 to non-escrowed accounts.
    168 
    169 \noindent
    170 The active operational risk stands at
    171 {\bf {{ coins.total_active_risk }}}.
    172 
    173 \noindent
    174 Loss (actualized risk from recoups) is
    175 {\bf {{ coins.total_recoup_loss }}}.
    176 
    177 \noindent
    178 Losses from irregular reserve operations are at
    179 {\bf {{ reserves.total_irregular_loss }}} (reserves).
    180 
    181 \section{Income}
    182 
    183 This section analyzes the income of the exchange operator from fees.
    184 
    185 \begin{table}[h!]
    186 \begin{center}
    187   \caption{Fee revenue summary}
    188   \label{table:revenue}
    189   \begin{tabular}{l|r}
    190     Category    & Amount  \\ \hline \hline
    191   Withdraw fees & {{ reserves.total_withdraw_fee_income }} \\
    192   Deposit fees  & {{ coins.total_deposit_fee_income }} \\
    193   Melt fees     & {{ coins.total_melt_fee_income }} \\
    194   Refund fees   & {{ coins.total_refund_fee_income }} \\
    195   Aggregation fees & {{ aggregation.total_aggregation_fee_income }} \\
    196 \end{tabular}
    197 \end{center}
    198 \end{table}
    199 
    200 
    201 \section{Lag}
    202 
    203 This section analyzes lag, which can be due to some component being behind in
    204 executing transactions.  This is usually either the exchange's aggregator, the
    205 bank's wire transfer logic, or the synchronization of databases between
    206 exchange and auditor. Significant lag may be indicative of fraud, while
    207 moderate lag is indicative that the systems may be too slow to handle the
    208 load. Small amounts of lag can occur in normal operation.
    209 
    210 \subsection{Deposit lag}
    211 
    212 The total amount the exchange currently lags behind in deposits is
    213 {\bf {{ wire.total_amount_lag }}}.
    214 
    215 Note that some lag is perfectly normal, as tiny amounts that are too small to
    216 be wired are deferred beyond the due date, hoping that additional transfers
    217 will push them above the tiny threshold. Below, we report {\em non-tiny} wire
    218 transfers that are lagging behind.
    219 
    220 % Table generation tested by testcase #1 in test-auditor.sh
    221 
    222 {% if wire.lag_details|length() == 0 %}
    223   {\bf No non-tiny wire transfers that are lagging behind detected.}
    224 {% else %}
    225   \begin{longtable}{l|r|r}
    226   {\bf Deadline} & {\bf Amount} & {\bf Target account} \\ \hline \hline
    227 \endfirsthead
    228   {\bf Deadline} & {\bf Amount} & {\bf Target account} \\ \hline \hline
    229 \endhead
    230   \hline \hline
    231   {\bf Deadline} & {\bf Amount} & {\bf Target account} \\
    232 \endfoot
    233   \hline \hline
    234   {\bf Deadline} & {\bf Amount} & {\bf Target account} \\
    235     \caption{Lagging non-tiny transactions.}
    236     \label{table:lag}
    237 \endlastfoot
    238 {% for item in wire.lag_details %}
    239   {{ item.deadline }} &
    240   {{ item.total_amount }} &
    241   {\tt
    242     {% if 'account' in item %}
    243        {{ item.account }}
    244     {% endif %}
    245   } \\ \hline
    246 {% endfor %}
    247   \end{longtable}
    248 {% endif %}
    249 
    250 
    251 
    252 {% if wire.lag_kyc_details|length() == 0 %}
    253   {\bf No KYC-blocked non-tiny wire transfers that are lagging behind detected.}
    254 {% else %}
    255   \begin{longtable}{l|r|c|r}
    256   {\bf Deadline} & {\bf Amount} & {\bf Requirement} & {\bf Target account} \\ \hline \hline
    257 \endfirsthead
    258   {\bf Deadline} & {\bf Amount} & {\bf Requirement} & {\bf Target account} \\ \hline \hline
    259 \endhead
    260   \hline \hline
    261   {\bf Deadline} & {\bf Amount} & {\bf Requirement} & {\bf Target account} \\
    262 \endfoot
    263   \hline \hline
    264   {\bf Deadline} & {\bf Amount} & {\bf Requirement} & {\bf Target account} \\
    265     \caption{Lagging non-tiny transactions due to missing KYC data.}
    266     \label{table:lag}
    267 \endlastfoot
    268 {% for item in wire.lag_kyc_details %}
    269   {{ item.deadline }} &
    270   {{ item.amount }} &
    271   {{ item.kyc_pending }} &
    272   {\tt
    273     {% if 'account' in item %}
    274        {{ item.account }}
    275     {% endif %}
    276   } \\ \hline
    277 {% endfor %}
    278   \end{longtable}
    279 {% endif %}
    280 
    281 
    282 {% if wire.lag_aml_details|length() == 0 %}
    283   {\bf No non-tiny wire transfers that are lagging behind due to AML detected.}
    284 {% else %}
    285   \begin{longtable}{l|r|r}
    286   {\bf Deadline} & {\bf Amount}/{\bf Limit} & {\bf AML status} \\
    287   \multicolumn{3}{l}{\bf Target account} \\ \hline \hline
    288 \endfirsthead
    289   {\bf Deadline} & {\bf Amount}/{\bf Limit} & {\bf AML status} \\
    290   \multicolumn{4}{l}{\bf Target account} \\ \hline \hline
    291 \endhead
    292   \hline \hline
    293   {\bf Deadline} & {\bf Amount}/{\bf Limit} & {\bf AML status} \\
    294   \multicolumn{4}{l}{\bf Target account} \\
    295 \endfoot
    296   \hline \hline
    297   {\bf Deadline} & {\bf Amount}/{\bf Limit} & {\bf AML status} \\
    298   \multicolumn{4}{l}{\bf Target account} \\
    299     \caption{Lagging non-tiny transactions due to AML decisions.}
    300     \label{table:lag}
    301 \endlastfoot
    302 {% for item in wire.lag_aml_details %}
    303   {{ item.deadline }} &
    304   {{ item.amount }}/{{ item.aml_limit }} &
    305   {{ item.aml_status }} &
    306 \nopagebreak
    307   \multicolumn{4}{l}{ {\tt
    308     {% if 'account' in item %}
    309        {{ item.account }}
    310     {% endif %}
    311   } } \\ \hline
    312 {% endfor %}
    313   \end{longtable}
    314 {% endif %}
    315 
    316 
    317 \subsection{Reserve closure lag}
    318 
    319 The total amount the exchange currently lags behind in reserve closures is
    320 {\bf {{ wire.total_closure_amount_lag }}}.
    321 
    322 Note that some minimal lag may be normal as transactions may be in-flight.
    323 
    324 % Table generation tested by testcase #21 in test-auditor.sh
    325 
    326 {% if wire.reserve_lag_details|length() == 0 %}
    327   {\bf No closure transfers that are lagging behind detected.}
    328 {% else %}
    329   \begin{longtable}{l|r|r}
    330   {\bf Deadline} & {\bf Amount} & {\bf Row} \\
    331   \multicolumn{3}{l}{\bf WTID} \\
    332   \multicolumn{3}{l}{\bf Target account} \\ \hline \hline
    333 \endfirsthead
    334   {\bf Deadline} & {\bf Amount} & {\bf Row} \\
    335   \multicolumn{3}{l}{\bf WTID} \\
    336   \multicolumn{3}{l}{\bf Target account} \\ \hline \hline
    337 \endhead
    338   \hline \hline
    339   {\bf Deadline} & {\bf Amount} & {\bf Row} \\
    340   \multicolumn{3}{l}{\bf WTID} \\
    341   \multicolumn{3}{l}{\bf Target account} \\
    342 \endfoot
    343   \hline \hline
    344   {\bf Deadline} & {\bf Amount} & {\bf Row} \\
    345   \multicolumn{3}{l}{\bf WTID} \\
    346   \multicolumn{3}{l}{\bf Target account} \\
    347     \caption{Lagging reserve closure transactions.}
    348     \label{table:lag}
    349 \endlastfoot
    350 {% for item in wire.reserve_lag_details %}
    351   {{ item.deadline }} &
    352   {{ item.amount }} &
    353   {{ item.row }} \\
    354 \nopagebreak
    355   \multicolumn{3}{l}{ {\tt \small {{ item.wtid }} } } \\
    356 \nopagebreak
    357   \multicolumn{3}{l}{ {\tt
    358     {% if 'payto_uri' in item.account %}
    359        {{ item.account.payto_uri }}
    360     {% endif %}
    361   } } \\ \hline
    362 {% endfor %}
    363   \end{longtable}
    364 {% endif %}
    365 
    366 
    367 \subsection{Deposit confirmation lag}
    368 
    369 This section analyzes the lag, which is by how much the exchange's
    370 database reporting is behind in providing us with information about
    371 deposit confirmations. Merchants probabilistically report deposit
    372 confirmations to the auditor directly, so if the exchange is slow at
    373 synchronizing its database with the auditor, some deposit
    374 confirmations may be known at the auditor only directly. However, any
    375 delta not accounted for by database synchronization delays is an
    376 indicator of a malicious exchange (or online signing key compromise)
    377 and should be answered by revoking the exchange's online signing keys.
    378 % TODO: maybe reference PhD thesis on this?
    379 
    380 The total amount the exchange currently lags behind is
    381 {\bf {{ deposits.missing_deposit_confirmation_total }} } from a total number of
    382 {\bf {{ deposits.missing_deposit_confirmation_count }} } deposit confirmations.
    383 
    384 Note that some lag is perfectly normal.
    385 Below, we report {\em all} deposit confirmations that are lagging behind.
    386 
    387 % Table generation tested by testcase #24 in test-auditor.sh
    388 
    389 {% if deposits.deposit_confirmation_inconsistencies|length() == 0 %}
    390   {\bf No deposit confirmations that are lagging behind detected.}
    391 {% else %}
    392   \begin{longtable}{r|r|r}
    393   {\bf Timestamp} & {\bf Amount} & {\bf Row} \\
    394   \multicolumn{3}{l}{\bf Target account} \\ \hline \hline
    395 \endfirsthead
    396   {\bf Timestamp} & {\bf Amount} & {\bf Row} \\
    397   \multicolumn{3}{l}{\bf Target account} \\ \hline \hline
    398 \endhead
    399   \hline \hline
    400   {\bf Timestamp} & {\bf Amount} & {\bf Row} \\
    401   \multicolumn{3}{l}{\bf Target account} \\
    402 \endfoot
    403   \hline \hline
    404   {\bf Timestamp} & {\bf Amount} & {\bf Row} \\
    405   \multicolumn{3}{l}{\bf Target account} \\
    406     \caption{Missing deposit confirmations.}
    407     \label{table:missing_dc}
    408 \endlastfoot
    409 {% for item in deposits.deposit_confirmation_inconsistencies %}
    410   {{ item.timestamp }} &
    411   {{ item.amount }} &
    412   {{ item.rowid }} \\
    413 \nopagebreak
    414   \multicolumn{3}{l}{ {\tt \truncate{0.95\textwidth}{ {{ item.account }} } } } \\ \hline
    415 {% endfor %}
    416   \end{longtable}
    417 {% endif %}
    418 
    419 
    420 \section{Major irregularities}
    421 
    422 This section describes the possible major irregularities that the
    423 auditor has checked, and lists all of the actual irregularities
    424 encountered in detail.
    425 
    426 \subsection{Emergencies}
    427 
    428 Emergencies are errors where more coins were deposited than the
    429 exchange remembers issuing.  This usually means that the private keys
    430 of the exchange were compromised (stolen or factored) and subsequently
    431 used to sign coins off the books.  If this happens, all coins of the
    432 respective denomination that the exchange has redeemed so far may have
    433 been created by the attacker, and the exchange would have to refund
    434 all of the outstanding coins from ordinary users.  Thus, the {\bf risk
    435 exposure} is the amount of coins in circulation for a particular
    436 denomination and the maximum loss for the exchange from this type of
    437 compromise.
    438 
    439 {% if (coins.emergencies|length() != 0) %}
    440 The total risk from emergencies detected by amount is
    441 {\bf {{ coins.emergencies_risk_by_amount }} }.
    442 The total loss from emergencies detected by amount is
    443 {\bf {{ coins.emergencies_loss }} }.
    444 {% endif %}
    445 
    446 {% if (coins.emergencies_by_count|length() != 0) %}
    447 The total risk from emergencies detected by counting coins is
    448 {\bf {{ coins.emergencies_risk_by_count }} }
    449 The total loss from emergencies detected by counting coins could be up to
    450 {\bf {{ coins.emergencies_loss_by_count }} }.
    451 {% endif %}
    452 
    453 
    454 \subsubsection{Emergencies by counting coins}
    455 
    456 % Table generation tested by testcase #18 in test-auditor.sh
    457 
    458 {% if coins.emergencies_by_count|length() == 0 %}
    459   {\bf No emergencies detected by counting coins.}
    460 {% else %}
    461   \begin{longtable}{r|c|r|r}
    462   \multicolumn{4}{c}{ {\bf Public key hash} } \\
    463   {\bf Denomination} & {\bf Lifetime} & {\bf \# Issued}  & {\bf \# Deposited} \\ \hline \hline
    464 \endfirsthead
    465   \multicolumn{4}{|c|}{ {\bf Public key hash} } \\
    466   {\bf Denomination} & {\bf Lifetime} & {\bf \# Issued}  & {\bf \# Deposited} \\ \hline \hline
    467 \endhead
    468   \hline \hline
    469   \multicolumn{4}{|c|}{ {\bf Public key hash} } \\
    470   {\bf Denomination} & {\bf Lifetime} & {\bf \# Issued}  & {\bf \# Deposited} \\ \hline \hline
    471 \endfoot
    472     \caption{Emergencies by counting coins.}
    473     \label{table:emergencies_coin_counting}
    474 \endlastfoot
    475 {% for item in coins.emergencies_by_count %}
    476   \multicolumn{4}{l}{ {\tt \truncate{0.95\textwidth}{ {{ item.denompub_hash }} } } } \\
    477 \nopagebreak
    478   {{ item.value }} &
    479   {\tiny \begin{tabular}{c}
    480           {{ item.start }} \\ \hline
    481           {{ item.deposit_end }}
    482          \end{tabular} } &
    483   {{ item.num_issued }} &
    484   {{ item.num_known }} \\ \hline
    485 {% endfor %}
    486   \end{longtable}
    487 {% endif %}
    488 
    489 
    490 \subsubsection{Emergencies by value deposited}
    491 
    492 Note that emergencies by value deposited can {\em also} arise if the exchange
    493 fails to properly detect double spending (or simply fails to properly account
    494 for the remaining balance of a coin).  Thus, if issues are listed here {\bf in
    495 combination with} arithmetic problems (Section~\ref{sec:arithmetic}) issues,
    496 then they may not be a definitive indicator that the exchange's private
    497 signing key was compromised.
    498 
    499 % Table generation tested by testcases #18, #25 in test-auditor.sh
    500 
    501 {% if coins.emergencies|length() == 0 %}
    502   {\bf No emergencies by value detected.}
    503 {% else %}
    504   \begin{longtable}{r|c|r|r}
    505   \multicolumn{4}{c}{ {\bf Public key hash} } \\
    506   {\bf Denomination} & {\bf Lifetime} & {\bf Risk exposure}  & {\bf Loss} \\ \hline \hline
    507 \endfirsthead
    508   \multicolumn{4}{|c|}{ {\bf Public key hash} } \\
    509   {\bf Denomination} & {\bf Lifetime} & {\bf Risk exposure}  & {\bf Loss} \\ \hline \hline
    510 \endhead
    511   \hline \hline
    512   \multicolumn{4}{|c|}{ {\bf Public key hash} } \\
    513   {\bf Denomination} & {\bf Lifetime} & {\bf Risk exposure} & {\bf Loss} \\
    514 \endfoot
    515     \caption{Emergencies by value deposited.}
    516     \label{table:emergencies}
    517 \endlastfoot
    518 {% for item in coins.emergencies %}
    519   \multicolumn{4}{l}{ {\tt \truncate{0.95\textwidth}{ {{ item.denompub_hash }} } } } \\
    520 \nopagebreak
    521   {{ item.value }} &
    522   {\tiny \begin{tabular}{c}
    523           {{ item.start }} \\ \hline
    524           {{ item.deposit_end }}
    525          \end{tabular} } &
    526   {{ item.denom_risk }} &
    527   {{ item.denom_loss }} \\ \hline
    528 {% endfor %}
    529   \end{longtable}
    530 {% endif %}
    531 
    532 
    533 \subsection{Arithmetic problems} \label{sec:arithmetic}
    534 
    535 This section lists cases where the arithmetic of the exchange
    536 involving amounts disagrees with the arithmetic of the auditor.
    537 Disagreements imply that either the exchange made a loss (sending out
    538 too much money), or screwed a customer (and thus at least needs to fix
    539 the financial damage done to the customer).
    540 
    541 Note that the deltas only sum up the issues where $P \not= 0$ as only
    542 then we can tell if the problem lead to a profit or loss.
    543 
    544 The {\bf P} column is set to "1" if the arithmetic problem was be determined to be
    545 profitable for the exchange, "-1" if the problem resulted in a net loss for
    546 the exchange, and "0" if this is unclear or at least the gain/loss is not
    547 easily determined from the amounts and thus not included in the totals.
    548 
    549 \subsubsection{For aggregation}
    550 
    551 % Table generation tested by testcase #XX in test-auditor.sh
    552 
    553 {% if aggregation.amount_arithmetic_inconsistencies|length() == 0 %}
    554   {\bf No arithmetic problems detected.}
    555 {% else %}
    556   \begin{longtable}{p{3.5cm}|r|r|r|c}
    557   {\bf Operation} & {\bf Row} & {\bf Exchange} & {\bf Auditor} & {\bf P} \\
    558   \hline \hline
    559 \endfirsthead
    560   {\bf Operation} & {\bf Row} & {\bf Exchange} & {\bf Auditor} & {\bf P} \\ \hline \hline
    561 \endhead
    562   \hline \hline
    563   {\bf Operation} & {\bf Row} & {\bf Exchange} & {\bf Auditor} & {\bf P} \\
    564 \endfoot
    565   \hline \hline
    566   \multicolumn{2}{l|}{ {\bf $\sum$ Deltas (Auditor-Exchange)} } &
    567   + {{ aggregation.total_arithmetic_delta_plus }} &
    568   - {{ aggregation.total_arithmetic_delta_minus }} & \\
    569     \caption{Arithmetic inconsistencies.}
    570     \label{table:amount:arithmetic:inconsistencies:aggregation}
    571 \endlastfoot
    572 {% for item in aggregation.amount_arithmetic_inconsistencies %}
    573   \truncate{3.3cm}{ {\tiny {{ item.operation }} } } &
    574   {{ item.rowid }} &
    575   {{ item.exchange }} &
    576   {{ item.auditor }} &
    577   {{ item.profitable }} \\ \hline
    578 {% endfor %}
    579   \end{longtable}
    580 {% endif %}
    581 
    582 \subsubsection{For coins}
    583 
    584 % Table generation tested by testcase #18 in test-auditor.sh
    585 % Table generation tested by testcase #3 in test-revocation.sh
    586 
    587 {% if coins.amount_arithmetic_inconsistencies|length() == 0 %}
    588   {\bf No arithmetic problems detected.}
    589 {% else %}
    590   \begin{longtable}{p{3.5cm}|r|r|r|c}
    591   {\bf Operation} & {\bf Row} & {\bf Exchange} & {\bf Auditor} & {\bf P} \\
    592   \hline \hline
    593 \endfirsthead
    594   {\bf Operation} & {\bf Row} & {\bf Exchange} & {\bf Auditor} & {\bf P} \\ \hline \hline
    595 \endhead
    596   \hline \hline
    597   {\bf Operation} & {\bf Row} & {\bf Exchange} & {\bf Auditor} & {\bf P} \\
    598 \endfoot
    599   \hline \hline
    600   \multicolumn{2}{l|}{ {\bf $\sum$ Deltas (Auditor-Exchange)} } &
    601   + {{ coins.total_arithmetic_delta_plus }} &
    602   - {{ coins.total_arithmetic_delta_minus }} & \\
    603     \caption{Arithmetic inconsistencies.}
    604     \label{table:amount:arithmetic:inconsistencies:coins}
    605 \endlastfoot
    606 {% for item in coins.amount_arithmetic_inconsistencies %}
    607   \truncate{3.3cm}{ {\tiny {{ item.operation }} } } &
    608   {{ item.rowid }} &
    609   {{ item.exchange }} &
    610   {{ item.auditor }} &
    611   {{ item.profitable }} \\ \hline
    612 {% endfor %}
    613   \end{longtable}
    614 {% endif %}
    615 
    616 \subsubsection{For reserves}
    617 
    618 % Table generation tested by testcase #2 in test-auditor.sh
    619 
    620 {% if reserves.amount_arithmetic_inconsistencies|length() == 0 %}
    621   {\bf No arithmetic problems detected.}
    622 {% else %}
    623   \begin{longtable}{p{3.5cm}|r|r|r|c}
    624   {\bf Operation} & {\bf Row} & {\bf Exchange} & {\bf Auditor} & {\bf P} \\
    625   \hline \hline
    626 \endfirsthead
    627   {\bf Operation} & {\bf Row} & {\bf Exchange} & {\bf Auditor} & {\bf P} \\ \hline \hline
    628 \endhead
    629   \hline \hline
    630   {\bf Operation} & {\bf Row} & {\bf Exchange} & {\bf Auditor} & {\bf P} \\
    631 \endfoot
    632   \hline \hline
    633   \multicolumn{2}{l|}{ {\bf $\sum$ Deltas (Auditor-Exchange)} } &
    634   + {{ reserves.total_arithmetic_delta_plus }} &
    635   - {{ reserves.total_arithmetic_delta_minus }} & \\
    636     \caption{Arithmetic inconsistencies.}
    637     \label{table:amount:arithmetic:inconsistencies:reserves}
    638 \endlastfoot
    639 {% for item in reserves.amount_arithmetic_inconsistencies %}
    640   \truncate{3.3cm}{ {\tiny {{ item.operation }} } } &
    641   {{ item.rowid }} &
    642   {{ item.exchange }} &
    643   {{ item.auditor }} &
    644   {{ item.profitable }} \\ \hline
    645 {% endfor %}
    646   \end{longtable}
    647 {% endif %}
    648 
    649 
    650 \subsection{Reserve withdrawals exceeding balance}
    651 
    652 This section highlights cases where more coins were withdrawn from a
    653 reserve than the reserve contained funding for.  This is a serious
    654 compromise resulting in proportional financial losses to the exchange.
    655 
    656 % Table generation tested by testcase #2 in test-auditor.sh
    657 
    658 {% if reserves.reserve_balance_insufficient_inconsistencies|length() == 0 %}
    659   {\bf All withdrawals were covered by sufficient reserve funding.}
    660 {% else %}
    661   \begin{longtable}{p{8.5cm}|r}
    662   {\bf Reserve} & {\bf Loss}  \\ \hline \hline
    663 \endfirsthead
    664   {\bf Reserve} & {\bf Loss}  \\ \hline \hline
    665 \endhead
    666   \hline \hline
    667   {\bf Reserve} & {\bf Loss}
    668 \endfoot
    669   \hline
    670   {\bf Total loss} &
    671   {{ reserves.total_irregular_loss }} \\
    672   \caption{Reserves with withdrawals higher than reserve funding.}
    673   \label{table:reserve:balance_insufficient}
    674 \endlastfoot
    675 {% for item in reserves.reserve_balance_insufficient_inconsistencies %}
    676   {\tt \small {{ item.reserve_pub }} }
    677   &
    678   {{ item.loss }} \\ \hline
    679 {% endfor %}
    680   \end{longtable}
    681 {% endif %}
    682 
    683 
    684 \subsection{Claimed outgoing wire transfer inconsistencies}
    685 
    686 This section is about the exchange's database containing a
    687 justification to make an outgoing wire transfer for an aggregated
    688 amount for various deposits. It is reported as an inconsistency if the
    689 amount claimed for the wire transfer does not match up the deposits
    690 aggregated.  This is about a {\em claimed} outgoing wire transfer as
    691 violations do not imply that the wire transfer was actually made (as
    692 that is a separate check).  Note that not making the wire transfer
    693 would be reported separately in Section~\ref{sec:wire_check_out}.
    694 
    695 % Table generation tested by testcase #23 in test-auditor.sh
    696 
    697 {% if aggregation.wire_out_inconsistencies|length() == 0 %}
    698   {\bf All aggregations matched up.}
    699 {% else %}
    700   \begin{longtable}{r|r|r}
    701   \multicolumn{3}{c}{ {\bf Destination account} } \\
    702   {\bf Row} & {\bf Expected} & {\bf Claimed} \\ \hline \hline
    703 \endfirsthead
    704   \multicolumn{3}{c}{ {\bf Destination account} } \\
    705   {\bf Row} & {\bf Expected} & {\bf Claimed} \\ \hline \hline
    706 \endhead
    707   \hline \hline
    708   \multicolumn{3}{c}{ {\bf Destination account} } \\
    709   {\bf Row} & {\bf Expected} & {\bf Claimed} \\
    710 \endfoot
    711   \hline
    712   {\bf Total deltas}  &
    713   {{ aggregation.total_wire_out_delta_plus}} &
    714   - {{ aggregation.total_wire_out_delta_minus}} \\
    715   \caption{Claimed wire out aggregate totals not matching up.}
    716   \label{table:reserve:wire_out_balance_inconsistencies}
    717 \endlastfoot
    718 {% for item in aggregation.wire_out_inconsistencies %}
    719   \multicolumn{3}{l}{ {\tt \truncate{0.95\textwidth}{
    720     {% if 'payto_uri' in item.destination_account %}
    721         {{ item.destination_account.payto_uri }}
    722     {% endif %}
    723    } } } \\
    724 \nopagebreak
    725   {{ item.rowid }} &
    726   {{ item.expected }} &
    727   {{ item.claimed }} \\ \hline
    728 {% endfor %}
    729   \end{longtable}
    730 {% endif %}
    731 
    732 
    733 \subsection{Coin history inconsistencies}
    734 
    735 This section lists cases where the exchange made arithmetic errors found when
    736 looking at the transaction history of a coin.  The totals sum up the differences
    737 in amounts that matter for profit/loss calculations of the exchange. When an
    738 exchange merely shifted money from customers to merchants (or vice versa) without
    739 any effects on its own balance, those entries are excluded from the total.
    740 
    741 % Table generation tested by testcase #25 in test-auditor.sh
    742 
    743 {% if aggregation.coin_inconsistencies|length() == 0 %}
    744   {\bf All coin histories were unproblematic.}
    745 {% else %}
    746   \begin{longtable}{p{1.8cm}|r|r}
    747   {\bf Operation} & \multicolumn{2}{|c}{\bf Coin public key} \\
    748                   & {\bf Exchange } & {\bf Auditor} \\
    749   \hline \hline
    750 \endfirsthead
    751   {\bf Operation} & \multicolumn{2}{|r}{\bf Coin public key} \\
    752                   & {\bf Exchange } & {\bf Auditor} \\
    753   \hline \hline
    754 \endhead
    755   \hline \hline
    756   {\bf Operation} & \multicolumn{2}{|r}{\bf Coin public key} \\
    757                   & {\bf Exchange } & {\bf Auditor} \\
    758 \endfoot
    759   \hline
    760   $\sum$ {\bf Delta (Auditor-Exchange)} &
    761   {{ aggregation.total_coin_delta_plus }} &
    762   - {{ aggregation.total_coin_delta_minus }} \\
    763     \caption{Arithmetic inconsistencies of amount calculations involving a coin.}
    764     \label{table:amount:arithmetic:coin:inconsistencies}
    765 \endlastfoot
    766 {% for item in aggregation.coin_inconsistencies %}
    767   {{ item.operation }} &
    768   \multicolumn{2}{l}{ {\tt \small {{ item.coin_pub }} } } \\
    769 \nopagebreak &
    770   {{ item.exchange }} &
    771   {{ item.auditor }} \\ \hline
    772 {% endfor %}
    773   \end{longtable}
    774 {% endif %}
    775 
    776 
    777 \subsection{Operations with bad signatures}
    778 
    779 This section lists operations that the exchange performed, but for
    780 which the signatures provided are invalid. Hence the operations were
    781 invalid and the amount involved should be considered lost.
    782 
    783 \subsubsection{For aggregation}
    784 
    785 % Table generation tested by testcase #32 in test-auditor.sh
    786 
    787 {% if aggregation.bad_sig_losses|length() == 0 %}
    788   {\bf All signatures were valid.}
    789 {% else %}
    790   \begin{longtable}{l|r|r}
    791   \multicolumn{3}{l}{ {\bf Coin public key} }\\
    792   {\bf Operation type} & Database row & {\bf Loss amount} \\
    793   \hline \hline
    794 \endfirsthead
    795   \multicolumn{3}{l}{ {\bf Coin public key} }\\
    796   {\bf Operation type} & Database row & {\bf Loss amount} \\ \hline \hline
    797 \endhead
    798   \hline \hline
    799   \multicolumn{3}{l}{ {\bf Coin public key} }\\
    800   {\bf Operation type} & Database row & {\bf Loss amount} \\
    801 \endfoot
    802   \hline
    803   \multicolumn{2}{l}{ {\bf Total losses} } &
    804   {\bf {{ aggregation.total_bad_sig_loss}} } \\
    805   \caption{Losses from operations performed on coins without proper signatures.}
    806   \label{table:bad_signature_losses}
    807 \endlastfoot
    808 {% for item in aggregation.bad_sig_losses %}
    809   \multicolumn{3}{l}{ {\tt \small \truncate{0.9\textwidth}{ {{ item.coin_pub }} } } } \\
    810 \nopagebreak
    811   {{ item.operation }} &
    812   {{ item.row }} &
    813   {{ item.loss }} \\ \hline
    814 {% endfor %}
    815   \end{longtable}
    816 {% endif %}
    817 
    818 \subsubsection{For coins}
    819 
    820 % Table generation tested by testcase #4/#5/#6/#13 in test-auditor.sh
    821 % Table generation tested by testcase #4 in test-revocation.sh
    822 
    823 {% if coins.bad_sig_losses|length() == 0 %}
    824   {\bf All signatures were valid.}
    825 {% else %}
    826   \begin{longtable}{l|r|r}
    827   \multicolumn{3}{l}{ {\bf Coin public key} }\\
    828   {\bf Operation type} & Database row & {\bf Loss amount} \\
    829   \hline \hline
    830 \endfirsthead
    831   \multicolumn{3}{l}{ {\bf Coin public key} }\\
    832   {\bf Operation type} & Database row & {\bf Loss amount} \\ \hline \hline
    833 \endhead
    834   \hline \hline
    835   \multicolumn{3}{l}{ {\bf Coin public key} }\\
    836   {\bf Operation type} & Database row & {\bf Loss amount} \\
    837 \endfoot
    838   \hline
    839   \multicolumn{2}{l}{ {\bf Total losses} } &
    840   {\bf {{ coins.irregular_loss}} } \\
    841   \caption{Losses from operations performed on coins without proper signatures.}
    842   \label{table:bad_signature_losses}
    843 \endlastfoot
    844 {% for item in coins.bad_sig_losses %}
    845   \multicolumn{3}{l}{ {\tt \small \truncate{0.9\textwidth}{ {{ item.coin_pub }} } } } \\
    846 \nopagebreak
    847   {{ item.operation }} &
    848   {{ item.row }} &
    849   {{ item.loss }} \\ \hline
    850 {% endfor %}
    851   \end{longtable}
    852 {% endif %}
    853 
    854 \subsubsection{For reserves}
    855 
    856 % Table generation tested by testcase #7 in test-auditor.sh
    857 
    858 The key given is always the key for which the signature verification step
    859 failed. This is the reserve public key for ``withdraw'' operations, the coin
    860 public key for ``recoup'' operations, and the master public key for
    861 ``recoup-master'' operations (where the master's signature on the revocation
    862 is invalid).
    863 
    864 
    865 {% if reserves.bad_sig_losses|length() == 0 %}
    866   {\bf All signatures were valid.}
    867 {% else %}
    868   \begin{longtable}{l|r|r}
    869   \multicolumn{3}{l}{ {\bf Public key} }\\
    870   {\bf Operation type} & Database row & {\bf Loss amount} \\
    871   \hline \hline
    872 \endfirsthead
    873   \multicolumn{3}{l}{ {\bf Public key} }\\
    874   {\bf Operation type} & Database row & {\bf Loss amount} \\ \hline \hline
    875 \endhead
    876   \hline \hline
    877   \multicolumn{3}{l}{ {\bf Public key} }\\
    878   {\bf Operation type} & Database row & {\bf Loss amount} \\
    879 \endfoot
    880   \hline
    881   \multicolumn{2}{l}{ {\bf Total losses} } &
    882   {\bf {{ reserves.total_bad_sig_loss}} } \\
    883   \caption{Losses from operations performed on coins without proper signatures.}
    884   \label{table:bad_signature_losses}
    885 \endlastfoot
    886 {% for item in reserves.bad_sig_losses %}
    887   \multicolumn{3}{l}{ {\tt \small \truncate{0.9\textwidth}{ {{ item.key_pub }} } } } \\
    888 \nopagebreak
    889   {{ item.operation }} &
    890   {{ item.row }} &
    891   {{ item.loss }} \\ \hline
    892 {% endfor %}
    893   \end{longtable}
    894 {% endif %}
    895 
    896 
    897 
    898 \subsection{Actual incoming wire transfers} \label{sec:wire_in}
    899 
    900 This section highlights cases where the exchange's record about
    901 incoming wire transfers does not match with that of the bank.
    902 
    903 % Table generation tested by testcase #3 and #8 in test-auditor.sh
    904 
    905 {% if wire.reserve_in_amount_inconsistencies|length() == 0 %}
    906   {\bf All incoming wire transfer amounts and subjects matched up.}
    907 {% else %}
    908   \begin{longtable}{p{5.5cm}|r|r}
    909   \multicolumn{2}{l}{ {\bf Reserve Public Key} ({\bf Row}) } \\
    910   \multicolumn{3}{l}{ {\bf Diagnostic} } \\
    911   {\bf When} & {\bf Wired} & {\bf Expected}  \\
    912   \hline \hline
    913 \endfirsthead
    914   \multicolumn{2}{l}{ {\bf Reserve Public Key} ({\bf Row}) } \\
    915   \multicolumn{3}{l}{ {\bf Diagnostic} } \\
    916   {\bf When} & {\bf Wired} & {\bf Expected}  \\
    917   \hline \hline
    918 \endhead
    919   \hline \hline
    920   \multicolumn{2}{l}{ {\bf Reserve Public Key} ({\bf Row}) } \\
    921   \multicolumn{3}{l}{ {\bf Diagnostic} } \\
    922   {\bf When} & {\bf Wired} & {\bf Expected}  \\
    923 \endfoot
    924   \hline \hline
    925   {\bf Total deltas}  &
    926   {{ wire.total_wire_in_delta_plus }} &
    927   - {{ wire.total_wire_in_delta_minus}} \\
    928   \caption{Incoming wire transfer amounts not matching up.}
    929   \label{table:wire_in:transfer_amount_inconsistencies}
    930 \endlastfoot
    931 {% for item in wire.reserve_in_amount_inconsistencies %}
    932   \multicolumn{3}{l}{ {\tt \small {{ item.reserve_pub }} } ({{ item.row }}) } \\
    933 \nopagebreak
    934   \multicolumn{3}{l}{ {{ item.diagnostic }} } \\
    935 \nopagebreak
    936   {{ item.timestamp }} &
    937   {{ item.amount_wired }} &
    938   {{ item.amount_exchange_expected }} \\
    939   \hline
    940 {% endfor %}
    941   \end{longtable}
    942 {% endif %}
    943 
    944 
    945 {% if wire.reserve_in_amount_inconsistencies|length() != 0 %}
    946 This means that there are inconsistencies in the exchange's
    947 claims about incoming wire transfers, amounting to:
    948 \begin{itemize}
    949 \item The exchange believing it received
    950 {\bf {{ wire.total_wire_in_delta_plus }} } {\em less} than it
    951 actually received in some reserves.
    952 \item The exchange believing that it received
    953 {\bf {{ wire.total_wire_in_delta_minus}} } {\em more} than it
    954 actually received in some reserves.
    955 \end{itemize}
    956 {% endif %}
    957 
    958 
    959 \subsection{Misattributed incoming wire transfers}
    960 
    961 This section lists cases where the sender account record of an
    962 incoming wire transfer differs between the exchange and the bank.
    963 This will cause funds to be sent to the wrong account when the reserve
    964 is closed and the remaining balance is refunded to the original
    965 account.
    966 
    967 % Table generation tested by testcase #9 in test-auditor.sh
    968 
    969 {% if wire.misattribution_in_inconsistencies|length() == 0 %}
    970   {\bf All incoming wire transfer sender accounts matched up.}
    971 {% else %}
    972   \begin{longtable}{p{8.5cm}|r}
    973   {\bf Reserve Public Key} & {\bf Amount} \\
    974   \hline \hline
    975 \endfirsthead
    976   {\bf Reserve Public Key} & {\bf Amount} \\
    977   \hline \hline
    978 \endhead
    979   \hline \hline
    980   {\bf Reserve Public Key} & {\bf Amount} \\
    981 \endfoot
    982   \hline
    983   {\bf Total amount}  &
    984   {{ wire.total_misattribution_in}} \\
    985   \caption{Incoming wire transfer sender accounts not matching up.}
    986   \label{table:wire_in:sender_account_inconsistencies}
    987 \endlastfoot
    988 {% for item in wire.misattribution_in_inconsistencies %}
    989   {\tt \small \truncate{8.3cm}{ {{ item.reserve_pub }} } } &
    990   {{ item.amount }} \\ \hline
    991 {% endfor %}
    992   \end{longtable}
    993 {% endif %}
    994 
    995 
    996 
    997 
    998 \subsection{Actual outgoing wire transfers} \label{sec:wire_check_out}
    999 
   1000 This section highlights cases where the exchange misbehaved
   1001 with respect to outgoing wire transfers.
   1002 
   1003 % Table generation tested by testcase #11 in test-auditor.sh
   1004 
   1005 {% if wire.wire_out_amount_inconsistencies|length() == 0 %}
   1006   {\bf All outgoing wire transfers matched up.}
   1007 {% else %}
   1008   \begin{longtable}{p{5.5cm}|r|r}
   1009   {\bf Wire transfer identifier} & {\bf Wired} & {\bf Justified}  \\
   1010   {\bf Account}                  & {\bf Row} & {\bf Timestamp}  \\
   1011   \hline \hline
   1012 \endfirsthead
   1013   {\bf Wire transfer identifier} & {\bf Wired} & {\bf Justified}  \\
   1014   {\bf Account}                  & {\bf Row} & {\bf Timestamp}  \\
   1015   \hline \hline
   1016 \endhead
   1017   \hline \hline
   1018   {\bf Wire transfer identifier} & {\bf Wired} & {\bf Justified}  \\
   1019   {\bf Account}                  & {\bf Row} & {\bf Timestamp}  \\
   1020 \endfoot
   1021   \hline
   1022   {\bf Total deltas}  &
   1023   {{ wire.total_wire_out_delta_plus }} &
   1024   - {{ wire.total_wire_out_delta_minus }} \\
   1025   \caption{Outgoing wire transfer amounts not matching up.}
   1026   \label{table:wire_out:transfer_amount_inconsistencies}
   1027 \endlastfoot
   1028 {% for item in wire.wire_out_amount_inconsistencies %}
   1029   {\tt \small \truncate{5.2cm}{ {{ item.wtid }} } } &
   1030   {{ item.amount_wired }} &
   1031   {{ item.amount_justified }} \\
   1032 \nopagebreak
   1033   {{ item.account_section }} &
   1034   {{ item.row }} &
   1035   {\tiny {{ item.timestamp }} } \\ \hline
   1036 {% endfor %}
   1037   \end{longtable}
   1038 {% endif %}
   1039 
   1040 
   1041 \section{Minor irregularities}
   1042 
   1043 \subsection{Denominations without auditor signature}
   1044 
   1045 This section highlights denomination keys that lack a proper
   1046 signature from the {\tt taler-auditor-offline} tool. This may be
   1047 legitimate, say in case where the auditor's involvement in the
   1048 exchange business is ending and a new auditor is responsible for
   1049 future denominations. So this must be read with a keen eye on the
   1050 business situation.
   1051 
   1052 
   1053 {% if coins.unsigned_denominations|length() == 0 %}
   1054   {\bf All denominations officially audited by this auditor.}
   1055 {% else %}
   1056   \begin{longtable}{p{6cm}|r|r|r}
   1057   {\bf Denomination} & {\bf Value} & {\bf Start} & {\bf End} \\ \hline \hline
   1058 \endfirsthead
   1059   {\bf Denomination} & {\bf Value} & {\bf Start} & {\bf End} \\ \hline \hline
   1060 \endhead
   1061   \hline \hline
   1062   {\bf Denomination} & {\bf Value} & {\bf Start} & {\bf End} \\ \hline \hline
   1063 \endfoot
   1064   \caption{Denominations not officially audited by this auditor.}
   1065   \label{table:denominations:denoms_without_signatures}
   1066 \endlastfoot
   1067 {% for item in coins.unsigned_denominations %}
   1068  {\tt \tiny {{ item.denomination }} } &
   1069   {{ item.value }} &
   1070   {{ item.start_time }} &
   1071   {{ item.end_time }} \\ \hline
   1072 {% endfor %}
   1073   \end{longtable}
   1074 {% endif %}
   1075 
   1076 \subsection{Incorrect reserve balance summary in database}
   1077 
   1078 This section highlights cases where the reserve balance summary
   1079 in the database does not match the calculations made by the auditor.
   1080 Deltas may indicate a corrupt database, but do not necessarily
   1081 translate into a financial loss (yet).
   1082 
   1083 % Table generation tested by testcase #3 in test-auditor.sh
   1084 % Table generation tested by testcase #4 in test-revocation.sh
   1085 
   1086 {% if reserves.reserve_balance_summary_wrong_inconsistencies|length() == 0 %}
   1087   {\bf All balances matched up.}
   1088 {% else %}
   1089   \begin{longtable}{p{6cm}|r|r}
   1090   {\bf Reserve} & {\bf Auditor} & {\bf Exchange} \\ \hline \hline
   1091 \endfirsthead
   1092   {\bf Reserve} & {\bf Auditor} & {\bf Exchange} \\ \hline \hline
   1093 \endhead
   1094   \hline \hline
   1095   {\bf Reserve} & {\bf Auditor} & {\bf Exchange}
   1096 \endfoot
   1097   \hline
   1098   \hline
   1099   {\bf Total deltas}  &
   1100   {{ reserves.total_balance_summary_delta_plus}} &
   1101   - {{ reserves.total_balance_summary_delta_minus}} \\
   1102   \caption{Reserves balances not matching up.}
   1103   \label{table:reserve:balance_inconsistencies}
   1104 \endlastfoot
   1105 {% for item in reserves.reserve_balance_summary_wrong_inconsistencies %}
   1106  {\tt \tiny {{ item.reserve_pub }} } &
   1107   {{ item.auditor }} &
   1108   {{ item.exchange }} \\ \hline
   1109 {% endfor %}
   1110   \end{longtable}
   1111 {% endif %}
   1112 
   1113 {% if reserves.reserve_balance_summary_wrong_inconsistencies|length() != 0 %}
   1114 This means that there are inconsistencies in the exchange's
   1115 summary data about reserve balances.
   1116 \begin{itemize}
   1117 \item The exchange believes some reserves contain (in total)
   1118 {\bf {{ reserves.total_balance_summary_delta_plus}} } {\em less} than they
   1119 actually contain.  A non-zero value here means the exchange may deny legitimate withdrawal
   1120 requests, denying customers access to their funds.
   1121 \item The exchange believes some reserves contain (in total)
   1122 {\bf {{ reserves.total_balance_summary_delta_minus}} } {\em more} than they
   1123 actually contain.  A non-zero value here means the exchange may allow coins to be withdrawn
   1124 for which it never received any income, at a loss (for the exchange).
   1125 \end{itemize}
   1126 
   1127 {% if wire.reserve_in_amount_inconsistencies|length() != 0 %}
   1128 Note that inconsistencies detected in Section~\ref{sec:wire_in} may
   1129 have created follow-up errors in this table.
   1130 {% endif %}
   1131 
   1132 {% endif %}
   1133 
   1134 
   1135 \subsection{Wire table issues}
   1136 
   1137 This section describes issues found by the wire auditor that do not
   1138 have a clear financial impact.
   1139 
   1140 % Table generation tested by testcase #17 in test-auditor.sh
   1141 
   1142 {% if wire.row_inconsistencies|length() == 0 %}
   1143   {\bf No wire row inconsistencies found.}
   1144 {% else %}
   1145   \begin{longtable}{p{5.5cm}|l|p{4.5cm}}
   1146   {\bf Table} & {\bf Row} & {\bf Diagnostic} \\
   1147   \hline \hline
   1148 \endfirsthead
   1149   {\bf Table} & {\bf Row} & {\bf Diagnostic} \\
   1150   \hline \hline
   1151 \endhead
   1152   \hline
   1153   {\bf Table} & {\bf Row} & {\bf Diagnostic} \\
   1154 \endfoot
   1155   \hline
   1156   {\bf Table} & {\bf Row} & {\bf Diagnostic} \\
   1157   \caption{Other wire table issues found (by table and row).}
   1158   \label{table:wire:misc}
   1159 \endlastfoot
   1160 {% for item in wire.row_inconsistencies %}
   1161   \verb! {{ item.table }} ! &
   1162   {{ item.row }} &
   1163   {{ item.diagnostic }} \\
   1164 \nopagebreak
   1165   \multicolumn{3}{l}{ {\tiny {\tt \truncate{\textwidth}{ {{ item.id }} } } } } \\ \hline
   1166 {% endfor %}
   1167   \end{longtable}
   1168 {% endif %}
   1169 
   1170 
   1171 \subsection{Outgoing wire transfer subject issues}
   1172 
   1173 This section describes issues found by the wire auditor that
   1174 relate to outgoing wire transfers subjects being duplicated.
   1175 
   1176 % Table generation tested by testcase #27 in test-auditor.sh
   1177 
   1178 {% if wire.wire_format_inconsistencies|length() == 0 %}
   1179   {\bf No wire format inconsistencies found.}
   1180 {% else %}
   1181   \begin{longtable}{p{6.5cm}|r}
   1182   \multicolumn{2}{c}{ {\bf Diagnostic} } \\
   1183   {\bf Row (base32)}  & {\bf Amount} \\
   1184   \hline \hline
   1185 \endfirsthead
   1186   \multicolumn{2}{c}{ {\bf Diagnostic} } \\
   1187     {\bf Row (base32)}  & {\bf Amount} \\
   1188   \hline \hline
   1189 \endhead
   1190   \hline
   1191   \multicolumn{2}{c}{ {\bf Diagnostic} } \\
   1192   {\bf Row (base32)}  & {\bf Amount} \\
   1193 \endfoot
   1194   \hline
   1195   \hline
   1196   {\bf Total} &
   1197   {{ wire.total_wire_format_amount }} \\
   1198   \caption{Outgoing wire transfer subject issues found.}
   1199   \label{table:outgoing:wtid}
   1200 \endlastfoot
   1201 {% for item in wire.wire_format_inconsistencies %}
   1202   \multicolumn{2}{l}{ \small \truncate{0.95\textwidth}{ {{ item.diagnostic }} } } \\
   1203 \nopagebreak
   1204   { \tt \small \truncate{0.95\textwidth}{ {{ item.wire_offset }} } } & {{ item.amount }} \\ \hline
   1205 {% endfor %}
   1206   \end{longtable}
   1207 {% endif %}
   1208 
   1209 
   1210 \subsection{Wire fee structure inconsistencies}
   1211 
   1212 This section lists cases where the exchange's database may be ambiguous
   1213 with respect to what wire fee it charges at what time.
   1214 
   1215 % Table generation tested by testcase #14 in test-auditor.sh
   1216 
   1217 {% if aggregation.wire_fee_time_inconsistencies|length() == 0 %}
   1218   {\bf No wire fee timing issues detected.}
   1219 {% else %}
   1220   \begin{longtable}{p{1.5cm}|r|p{6}}
   1221   {\bf Wire format} & {\bf Timestamp} & {\bf Diagnostic}
   1222   \\ \hline \hline
   1223 \endfirsthead
   1224   {\bf Wire format} & {\bf Timestamp} & {\bf Diagnostic}
   1225   \\ \hline \hline
   1226 \endhead
   1227   \hline \hline
   1228   {\bf Wire format} & {\bf Timestamp} & {\bf Diagnostic} \\
   1229 \endfoot
   1230   \hline \hline
   1231   {\bf Wire format} & {\bf Timestamp} & {\bf Diagnostic} \\
   1232   \caption{Wire fees with ambiguous timestamps.}
   1233   \label{table:wire_fee:ambiguity}
   1234 \endlastfoot
   1235 {% for item in aggregation.wire_fee_time_inconsistencies %}
   1236   {\tt {{ item.type }} } & {{ item.time }} & {{ item.diagnostic }} \\ \hline
   1237 {% endfor %}
   1238   \end{longtable}
   1239 {% endif %}
   1240 
   1241 
   1242 
   1243 \subsection{Other issues}
   1244 
   1245 This section describes issues found that do not have a clear financial
   1246 impact.
   1247 
   1248 \subsubsection{For aggregation}
   1249 
   1250 % Table generation tested by testcase #15/#25 in test-auditor.sh
   1251 
   1252 {% if aggregation.row_inconsistencies|length() == 0 %}
   1253   {\bf No row inconsistencies found.}
   1254 {% else %}
   1255   \begin{longtable}{p{2.5cm}|l|p{5cm}}
   1256   {\bf Table} & {\bf Row} & {\bf Diagnostic} \\
   1257   \hline \hline
   1258 \endfirsthead
   1259   {\bf Table} & {\bf Row} & {\bf Diagnostic} \\
   1260   \hline \hline
   1261 \endhead
   1262   \hline \hline
   1263   {\bf Table} & {\bf Row} & {\bf Diagnostic} \\
   1264 \endfoot
   1265   \hline \hline
   1266   {\bf Table} & {\bf Row} & {\bf Diagnostic} \\
   1267   \caption{Other issues found (by table and row).}
   1268   \label{table:misc:aggregation}
   1269 \endlastfoot
   1270 {% for item in aggregation.row_inconsistencies %}
   1271   \verb! {{ item.table }} ! &
   1272   {{ item.row }} &
   1273   {{ item.diagnostic }} \\ \hline
   1274 {% endfor %}
   1275   \end{longtable}
   1276 {% endif %}
   1277 
   1278 \subsubsection{For coins}
   1279 
   1280 % Table generation tested by testcase #13 in test-auditor.sh
   1281 
   1282 {% if coins.row_inconsistencies|length() == 0 %}
   1283   {\bf No row inconsistencies found.}
   1284 {% else %}
   1285   \begin{longtable}{p{2.5cm}|l|p{5cm}}
   1286   {\bf Table} & {\bf Row} & {\bf Diagnostic} \\
   1287   \hline \hline
   1288 \endfirsthead
   1289   {\bf Table} & {\bf Row} & {\bf Diagnostic} \\
   1290   \hline \hline
   1291 \endhead
   1292   \hline \hline
   1293   {\bf Table} & {\bf Row} & {\bf Diagnostic} \\
   1294 \endfoot
   1295   \hline \hline
   1296   {\bf Table} & {\bf Row} & {\bf Diagnostic} \\
   1297   \caption{Other issues found (by table and row).}
   1298   \label{table:misc:coins}
   1299 \endlastfoot
   1300 {% for item in coins.row_inconsistencies %}
   1301   \verb! {{ item.table }} ! &
   1302   {{ item.row }} &
   1303   {{ item.diagnostic }} \\ \hline
   1304 {% endfor %}
   1305   \end{longtable}
   1306 {% endif %}
   1307 
   1308 \subsubsection{For reserves}
   1309 
   1310 % Table generation tested by testcase #4 in test-revocation.sh
   1311 
   1312 {% if reserves.row_inconsistencies|length() == 0 %}
   1313   {\bf No row inconsistencies found.}
   1314 {% else %}
   1315   \begin{longtable}{p{2.5cm}|l|p{5cm}}
   1316   {\bf Table} & {\bf Row} & {\bf Diagnostic} \\
   1317   \hline \hline
   1318 \endfirsthead
   1319   {\bf Table} & {\bf Row} & {\bf Diagnostic} \\
   1320   \hline \hline
   1321 \endhead
   1322   \hline \hline
   1323   {\bf Table} & {\bf Row} & {\bf Diagnostic} \\
   1324 \endfoot
   1325   \hline \hline
   1326   {\bf Table} & {\bf Row} & {\bf Diagnostic} \\
   1327   \caption{Other issues found (by table and row).}
   1328   \label{table:misc:reserves}
   1329 \endlastfoot
   1330 {% for item in reserves.row_inconsistencies %}
   1331   \verb! {{ item.table }} ! &
   1332   {{ item.row }} &
   1333   {{ item.diagnostic }} \\ \hline
   1334 {% endfor %}
   1335   \end{longtable}
   1336 {% endif %}
   1337 
   1338 
   1339 \section{Delays and timing}
   1340 
   1341 This section describes issues that are likely caused simply by
   1342 some job process of the exchange not running properly or not having
   1343 caught up with the work load yet.
   1344 
   1345 \subsection{Delayed closure of reserves}
   1346 
   1347 This section describes cases where the exchange did not
   1348 close a reserve and wire back the remaining funds when the
   1349 reserve expired.
   1350 
   1351 % Table generation tested by testcase #20 in test-auditor.sh
   1352 
   1353 {% if reserves.reserve_not_closed_inconsistencies|length() == 0 %}
   1354   {\bf All expired reserves were closed.}
   1355 {% else %}
   1356   \begin{longtable}{p{4.5cm}|c|r}
   1357   {\bf Reserve} & {\bf Expired} & {\bf Balance} \\ \hline \hline
   1358 \endfirsthead
   1359   {\bf Reserve} & {\bf Expired} & {\bf Balance} \\ \hline \hline
   1360 \endhead
   1361   \hline \hline
   1362   {\bf Reserve} & {\bf Expired} & {\bf Balance}
   1363 \endfoot
   1364   \hline
   1365   {\bf Sum}     & &
   1366   {{ reserves.total_balance_reserve_not_closed}} \\
   1367   \caption{Reserves not closed on time.}
   1368   \label{table:reserve:not_closed}
   1369 \endlastfoot
   1370 {% for item in reserves.reserve_not_closed_inconsistencies %}
   1371   {\tt \tiny \truncate{4.3cm}{ {{ item.reserve_pub }} } } &
   1372   {\tiny {{ item.expiration_time }} } &
   1373   {{ item.balance }} \\ \hline
   1374 {% endfor %}
   1375   \end{longtable}
   1376 {% endif %}
   1377 
   1378 
   1379 \subsection{Hanging refresh operations}
   1380 
   1381 This section describes cases where the exchange booked a
   1382 coin as spent from {\tt /refresh/melt} but where the
   1383 wallet did not yet complete {\tt /refresh/reveal}.  This
   1384 may happen even if the exchange is correct.
   1385 
   1386 % Table generation tested by testcase #12 in test-auditor.sh
   1387 
   1388 {% if coins.refresh_hanging|length() == 0 %}
   1389   {\bf All melted coins were refreshed.}
   1390 {% else %}
   1391   \begin{longtable}{p{6.5cm}|c|r}
   1392   {\bf Key} & {\bf row} & {\bf Amount} \\
   1393   \hline \hline
   1394 \endfirsthead
   1395   {\bf Key} & {\bf row} & {\bf Amount} \\
   1396   \hline \hline
   1397 \endhead
   1398   \hline \hline
   1399   {\bf Key} & {\bf row} & {\bf Amount} \\
   1400 \endfoot
   1401   \hline
   1402   {\bf Sum}     & &
   1403   {{ coins.total_refresh_hanging}} \\
   1404   \caption{Refresh operations hanging.}
   1405   \label{table:refresh:hanging}
   1406 \endlastfoot
   1407 {% for item in coins.refresh_hanging %}
   1408   \truncate{6.2cm}{ {\tt \small {{ item.coin_pub }} } } &
   1409   {{ item.row }} &
   1410   {{ item.amount }} \\ \hline
   1411 {% endfor %}
   1412   \end{longtable}
   1413 {% endif %}
   1414 
   1415 
   1416 \subsection{Denomination key invalid at time of withdrawal}
   1417 
   1418 This section lists cases where a denomination key was not valid for
   1419 withdrawal at the time when the exchange claims to have signed a coin
   1420 with it.  This would be irregular, but has no obvious financial
   1421 implications.
   1422 
   1423 % Table generation tested by testcase #22 in test-auditor.sh
   1424 
   1425 {% if reserves.denomination_key_validity_withdraw_inconsistencies|length() == 0 %}
   1426   {\bf All denomination keys were valid at the time of withdrawals.}
   1427 {% else %}
   1428   \begin{longtable}{p{7.5cm}|r}
   1429   {\bf Reserve} & {\bf Table row} \\
   1430   {\bf Denomination key hash} & {\bf Execution time} \\ \hline \hline
   1431 \endfirsthead
   1432   {\bf Reserve} & {\bf Table row} \\
   1433   {\bf Denomination key hash} & {\bf Execution time} \\ \hline \hline
   1434 \endhead
   1435   \hline \hline
   1436   {\bf Reserve} & {\bf Table row} \\
   1437   {\bf Denomination key hash} & {\bf Execution time} \\
   1438 \endfoot
   1439   \hline
   1440   {\bf Reserve} & {\bf Table row} \\
   1441   {\bf Denomination key hash} & {\bf Execution time} \\
   1442   \caption{Execution times not matching denomination key validity period.}
   1443   \label{table:withdraw:bad_time}
   1444 \endlastfoot
   1445 {% for item in reserves.denomination_key_validity_withdraw_inconsistencies %}
   1446   {\tt \small \truncate{0.6\textwidth}{ {{ item.reserve_pub }} } } & {{ item.row }} \\
   1447 \nopagebreak
   1448   {\tt \small \truncate{0.6\textwidth}{ {{ item.denompub_h }} } } & {{ item.execution_date }} \\ \hline
   1449 {% endfor %}
   1450   \end{longtable}
   1451 {% endif %}
   1452 
   1453 
   1454 \subsection{Wire transfer timestamp issues}
   1455 
   1456 This section lists issues with wire transfers related to timestamps.
   1457 
   1458 % Table generation tested by testcase #10/#17 in test-auditor.sh
   1459 
   1460 {% if wire.row_minor_inconsistencies|length() == 0 %}
   1461   {\bf No timestamp issues detected.}
   1462 {% else %}
   1463   \begin{longtable}{p{3cm}|r|p{5cm}}
   1464   {\bf Table} & {\bf Row} & {\bf Diagnostic}
   1465   \\ \hline \hline
   1466 \endfirsthead
   1467   {\bf Table} & {\bf Row} & {\bf Diagnostic}
   1468   \\ \hline \hline
   1469 \endhead
   1470   \hline \hline
   1471   {\bf Table} & {\bf Row} & {\bf Diagnostic} \\
   1472 \endfoot
   1473   \hline \hline
   1474   {\bf Table} & {\bf Row} & {\bf Diagnostic} \\
   1475   \caption{Execution times not matching in wire transfers.}
   1476   \label{table:wire:bad_time}
   1477 \endlastfoot
   1478 {% for item in wire.row_minor_inconsistencies %}
   1479   \verb! {{ item.table }} ! & {{ item.row }} & {{ item.diagnostic }} \\ \hline
   1480 {% endfor %}
   1481   \end{longtable}
   1482 {% endif %}
   1483 
   1484 
   1485 \end{document}