depolymerization

wire gateway for Bitcoin/Ethereum
Log | Files | Refs | Submodules | README | LICENSE

depolymerizer-bitcoin-procedures.sql (5783B)


      1 --
      2 -- This file is part of TALER
      3 -- Copyright (C) 2025 Taler Systems SA
      4 --
      5 -- TALER is free software; you can redistribute it and/or modify it under the
      6 -- terms of the GNU General Public License as published by the Free Software
      7 -- Foundation; either version 3, or (at your option) any later version.
      8 --
      9 -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10 -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11 -- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     12 --
     13 -- You should have received a copy of the GNU General Public License along with
     14 -- TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 
     16 SET search_path TO depolymerizer_bitcoin;
     17 
     18 -- Remove all existing functions
     19 DO
     20 $do$
     21 DECLARE
     22   _sql text;
     23 BEGIN
     24   SELECT INTO _sql
     25         string_agg(format('DROP %s %s CASCADE;'
     26                         , CASE prokind
     27                             WHEN 'f' THEN 'FUNCTION'
     28                             WHEN 'p' THEN 'PROCEDURE'
     29                           END
     30                         , oid::regprocedure)
     31                   , E'\n')
     32   FROM   pg_proc
     33   WHERE  pronamespace = 'depolymerizer_bitcoin'::regnamespace;
     34 
     35   IF _sql IS NOT NULL THEN
     36     EXECUTE _sql;
     37   END IF;
     38 END
     39 $do$;
     40 
     41 CREATE FUNCTION taler_transfer(
     42   IN in_amount taler_amount,
     43   IN in_exchange_base_url TEXT,
     44   IN in_credit_acc TEXT,
     45   IN in_credit_name TEXT,
     46   IN in_request_uid BYTEA,
     47   IN in_wtid BYTEA,
     48   IN in_now INT8,
     49   -- Error status
     50   OUT out_request_uid_reuse BOOLEAN,
     51   OUT out_wtid_reuse BOOLEAN,
     52   -- Success return
     53   OUT out_transfer_row_id INT8,
     54   OUT out_created_at INT8
     55 )
     56 LANGUAGE plpgsql AS $$
     57 BEGIN
     58 -- Check for idempotence and conflict
     59 SELECT (amount != in_amount
     60           OR credit_acc != in_credit_acc
     61           OR credit_name != in_credit_name
     62           OR exchange_url != in_exchange_base_url
     63           OR wtid != in_wtid)
     64         ,id, created
     65   INTO out_request_uid_reuse, out_transfer_row_id, out_created_at
     66   FROM tx_out
     67   WHERE request_uid = in_request_uid;
     68 IF FOUND THEN
     69   out_wtid_reuse=FALSE;
     70   RETURN;
     71 END IF;
     72 out_request_uid_reuse=FALSE;
     73 
     74 -- Register exchange
     75 INSERT INTO tx_out (
     76   amount,
     77   exchange_url,
     78   credit_acc,
     79   credit_name,
     80   request_uid,
     81   wtid,
     82   created,
     83   status
     84 ) VALUES (
     85   in_amount,
     86   in_exchange_base_url,
     87   in_credit_acc,
     88   in_credit_name,
     89   in_request_uid,
     90   in_wtid,
     91   in_now,
     92   'requested'
     93 ) ON CONFLICT (wtid) DO NOTHING
     94   RETURNING id, created INTO out_transfer_row_id, out_created_at;
     95 out_wtid_reuse=NOT FOUND;
     96 IF out_wtid_reuse THEN
     97   RETURN;
     98 END IF;
     99 -- Notify new transaction
    100 PERFORM pg_notify('taler_out', out_transfer_row_id || '');
    101 END $$;
    102 COMMENT ON FUNCTION taler_transfer IS 'Create an outgoing taler transaction and register it';
    103 
    104 CREATE FUNCTION register_tx_in(
    105   IN in_amount taler_amount,
    106   IN in_debit_acc TEXT,
    107   IN in_reserve_pub BYTEA,
    108   IN in_received INT8,
    109   IN in_txid BYTEA,
    110   -- Error status
    111   OUT out_reserve_pub_reuse BOOLEAN,
    112   -- Success return
    113   OUT out_tx_row_id INT8,
    114   OUT out_valued_at INT8,
    115   OUT out_new BOOLEAN
    116 )
    117 LANGUAGE plpgsql AS $$
    118 BEGIN
    119 -- Check for idempotence and conflict
    120 SELECT (amount != in_amount OR debit_acc != in_debit_acc OR txid != in_txid), id, received
    121   INTO out_reserve_pub_reuse, out_tx_row_id, out_valued_at
    122   FROM tx_in
    123   WHERE reserve_pub = in_reserve_pub;
    124 out_new=NOT FOUND;
    125 IF FOUND THEN
    126   RETURN;
    127 END IF;
    128 out_reserve_pub_reuse=false;
    129 
    130 -- Insert new incoming transaction
    131 INSERT INTO tx_in (
    132   txid,
    133   amount,
    134   debit_acc,
    135   reserve_pub,
    136   received
    137 ) VALUES (
    138   in_txid,
    139   in_amount,
    140   in_debit_acc,
    141   in_reserve_pub,
    142   in_received
    143 ) RETURNING id, received INTO out_tx_row_id, out_valued_at;
    144 PERFORM pg_notify('taler_in', out_tx_row_id || '');
    145 END $$;
    146 COMMENT ON FUNCTION register_tx_in IS 'Register an incoming transaction idempotently';
    147 
    148 CREATE FUNCTION sync_out(
    149   IN in_txid BYTEA,
    150   IN in_replace_txid BYTEA,
    151   IN in_amount taler_amount,
    152   IN in_exchange_base_url TEXT,
    153   IN in_credit_acc TEXT,
    154   IN in_wtid BYTEA,
    155   IN in_created INT8,
    156   -- Success return
    157   OUT out_new BOOLEAN,
    158   OUT out_replaced BOOLEAN,
    159   OUT out_recovered BOOLEAN
    160 )
    161 LANGUAGE plpgsql AS $$
    162 DECLARE
    163   local_id INT8;
    164 BEGIN
    165 -- Check replacement
    166 IF in_replace_txid IS NOT NULL THEN
    167   UPDATE tx_out SET txid=in_txid, status='status' WHERE txid=in_replace_txid;
    168   IF FOUND THEN
    169     out_new=FALSE;
    170     out_replaced=FALSE;
    171     out_recovered=FALSE;
    172     RETURN;
    173   END IF;
    174 END IF;
    175 out_replaced=FALSE;
    176 out_new=NOT EXISTS(SELECT FROM tx_out WHERE wtid = in_wtid);
    177 
    178 IF out_new THEN
    179   INSERT INTO tx_out (
    180     amount,
    181     wtid,
    182     credit_acc,
    183     exchange_url,
    184     status,
    185     txid,
    186     created,
    187     request_uid
    188   ) VALUES (
    189     in_amount,
    190     in_wtid,
    191     in_credit_acc,
    192     in_exchange_base_url,
    193     'sent',
    194     in_txid,
    195     in_created,
    196     NULL
    197   ) RETURNING id INTO local_id;
    198   out_recovered=FALSE;
    199   PERFORM pg_notify('taler_out', local_id || '');
    200 ELSE 
    201   UPDATE tx_out SET txid=in_txid, status='sent' WHERE status='requested' AND wtid=in_wtid;
    202   out_recovered=FOUND;
    203 END IF;
    204 END $$;
    205 COMMENT ON FUNCTION sync_out IS 'Sync a debit blockchain state with local state';
    206 
    207 CREATE FUNCTION sync_bounce(
    208   IN in_txid BYTEA,
    209   IN in_bounced BYTEA,
    210   IN in_created INT8,
    211   -- Success return
    212   OUT out_new BOOLEAN,
    213   OUT out_recovered BOOLEAN
    214 )
    215 LANGUAGE plpgsql AS $$
    216 BEGIN
    217 out_new=NOT EXISTS(SELECT FROM bounce WHERE bounced = in_bounced);
    218 
    219 IF out_new THEN
    220   INSERT INTO bounce (
    221     created,
    222     bounced,
    223     txid,
    224     status
    225   ) VALUES (
    226     in_created,
    227     in_bounced,
    228     in_txid,
    229     'sent'
    230   );
    231   out_recovered=false;
    232 ELSE 
    233   UPDATE bounce SET txid=in_txid, status='sent' WHERE status!='sent' AND bounced=in_bounced;
    234   out_recovered=FOUND;
    235 END IF;
    236 END $$;
    237 COMMENT ON FUNCTION sync_bounce IS 'Sync a bounce blockchain state with local state';