diff options
Diffstat (limited to 'src/exchangedb/procedures.sql')
-rw-r--r-- | src/exchangedb/procedures.sql | 152 |
1 files changed, 123 insertions, 29 deletions
diff --git a/src/exchangedb/procedures.sql b/src/exchangedb/procedures.sql index aeed5de0..85accfc2 100644 --- a/src/exchangedb/procedures.sql +++ b/src/exchangedb/procedures.sql @@ -511,10 +511,7 @@ CREATE OR REPLACE FUNCTION exchange_do_deposit( IN in_coin_sig BYTEA, IN in_shard INT8, IN in_policy_blocked BOOLEAN, - IN in_policy_details VARCHAR, - IN in_policy_serial_id BYTEA, - IN in_policy_deadline SMALLINT, - IN in_policy_timeout_fulfilment_state SMALLINT, + IN in_policy_details_serial_id INT8, OUT out_exchange_timestamp INT8, OUT out_balance_ok BOOLEAN, OUT out_conflict BOOLEAN) @@ -522,34 +519,11 @@ LANGUAGE plpgsql AS $$ DECLARE wtsi INT8; -- wire target serial id -DECLARE - xdi INT8; -- eXstension details serial id BEGIN --- Shards: INSERT policy_details (by policy_details_serial_id) --- INSERT wire_targets (by h_payto), on CONFLICT DO NOTHING; +-- Shards: INSERT wire_targets (by h_payto), on CONFLICT DO NOTHING; -- INSERT deposits (by coin_pub, shard), ON CONFLICT DO NOTHING; -- UPDATE known_coins (by coin_pub) -IF NOT NULL in_policy_details -THEN - INSERT INTO exchange.policy_details - (serial_id - ,policy_options - ,deadline - ,timeout_fulfilment_state - ,fulfilment_state) - VALUES - (in_policy_serial_id - ,in_policy_details - ,in_policy_deadline - ,in_policy_timeout_fulfilment_state - ,0) -- 0 == pending - RETURNING policy_details_serial_id INTO xdi; -ELSE - xdi=NULL; -END IF; - - INSERT INTO exchange.wire_targets (wire_target_h_payto ,payto_uri) @@ -602,7 +576,8 @@ INSERT INTO exchange.deposits ,in_wire_salt ,in_h_payto ,in_policy_blocked - ,xdi) + ,in_policy_details_serial_id + ) ON CONFLICT DO NOTHING; IF NOT FOUND @@ -622,6 +597,7 @@ THEN AND wire_target_h_payto=in_h_payto AND coin_pub=in_coin_pub AND coin_sig=in_coin_sig; + -- AND policy_details_serial_id=in_policy_details_serial_id; -- FIXME: is this required for idempotency? IF NOT FOUND THEN @@ -2211,5 +2187,123 @@ BEGIN END $$; +CREATE OR REPLACE FUNCTION insert_or_update_policy_details( + IN in_policy_hash_code BYTEA, + IN in_policy_json VARCHAR, + IN in_deadline INT8, + IN in_commitment_val INT8, + IN in_commitment_frac INT4, + IN in_accumulated_total_val INT8, + IN in_accumulated_total_frac INT4, + IN in_fee_val INT8, + IN in_fee_frac INT4, + IN in_transferable_val INT8, + IN in_transferable_frac INT4, + IN in_fulfillment_state SMALLINT, + OUT out_policy_details_serial_id INT8, + OUT out_accumulated_total_val INT8, + OUT out_accumulated_total_frac INT4, + OUT out_fulfillment_state SMALLINT) +LANGUAGE plpgsql +AS $$ +DECLARE + cur_commiment_val INT8; + cur_commiment_frac INT4; + cur_accumulated_total_val INT8; + cur_accumulated_total_frac INT4; +BEGIN + -- First, try to create a new entry. + INSERT INTO policy_details + (policy_hash_code, + policy_json, + deadline, + commitment_val, + commitment_frac, + accumulated_total_val, + accumulated_total_frac, + fee_val, + fee_frac, + transferable_val, + transferable_frac, + fulfillment_state) + VALUES (in_policy_hash_code, + in_policy_json, + in_deadline, + in_commitment_val, + in_commitment_frac, + in_accumulated_total_val, + in_accumulated_total_frac, + in_fee_val, + in_fee_frac, + in_transferable_val, + in_transferable_frac, + in_fulfillment_state) + RETURNING (policy_details_serial_id, + accumulated_total_val, + accumulated_total_frac, + fulfillment_state) + INTO (out_policy_details_serial_id, + out_accumulated_total_val, + out_accumulated_total_frac, + out_fulfillment_state) + ON CONFLICT (policy_hash_code) DO NOTHING; + + -- If the insert was successful, return + -- We assume that the fullfilment_state was correct in first place. + IF FOUND THEN + RETURN; + END IF; + + -- We had a conflict, grab the parts we need to update. + SELECT (policy_details_serial_id, + commitment_val, + commitment_frac, + accumulated_total_val, + accumulated_total_frac) + INTO (out_policy_details_serial_id, + cur_commitment_val, + cur_commitment_frac, + cur_accumulated_total_val, + cur_accumulated_total_frac) + FROM policy_details + WHERE policy_hash_code = in_policy_hash_code; + + -- calculate the new values (overflows throws exception) + out_accumulated_total_val = cur_accumulated_total_val + in_accumulated_total_val; + out_accumulated_total_frac = cur_accumulated_total_frac + in_accumulated_total_frac; + -- normalize + out_accumulated_total_val = out_accumulated_total_val + out_accumulated_total_frac / 100000000; + out_accumulated_total_frac = out_accumulated_total_frac % 100000000; + + IF (out_accumulated_total_val > (1 << 52)) + THEN + RAISE EXCEPTION "accumulation overflow"; + END IF; + + + -- Set the fulfillment_state according to the values. + -- For now, we only update the state when it was INSUFFICIENT. + -- FIXME: What to do in case of Failure or other state? + IF (out_fullfillment_state = 1) -- INSUFFICIENT + THEN + IF (out_accumulated_total_val >= cur_commitment_val OR + (out_accumulated_total_val = cur_commitment_val AND + out_accumulated_total_frac >= cur_commitment_frac)) + THEN + out_fulfillment_state = 2; -- READY + END IF; + END IF; + + -- Now, update the record + UPDATE exchange.policy_details + SET + accumulated_val = out_accumulated_total_val, + accumulated_frac = out_accumulated_total_frac, + fulfillment_state = out_fulfillment_state + WHERE + policy_details_serial_id = out_policy_details_serial_id; +END $$; + + COMMIT; |