Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions ENTITY_V3_EEP_CONFORMANCE_MANIFEST.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@
"files": [
{
"path": "src/31_Profiles/exchange_protocol.py",
"sha256": "cca451e553ea70a778c983805d155f05bb92baab5f481f75a60084a92e48d9f6"
"sha256": "53761f15c7ae58726ce8cd01a28164d3a14ae29aac38a89859c408fc3c76b14a"
},
{
"path": "src/32_V3_Hardening/exchange_protocol.py",
"sha256": "a631e259d2f0d7e4c4abf3acf1c04586e22bf5072928e5f9a9ddc3c130713637"
"sha256": "767e2a83a7ab5a71256c4f9535b75d91e7d33c97aaa7b7cefc617ffa7874bf41"
},
{
"path": "protocol/v3/ENTITY_EXCHANGE_PROTOCOL_DRAFT.md",
Expand Down Expand Up @@ -95,10 +95,11 @@
"sell admission rechecks unreserved entitlement atomically under concurrent submissions",
"concurrent matchers cannot create duplicate trades from the same executable orders",
"concurrent settlement attempts commit at most one entitlement transfer",
"revenue-event persistence is atomic with hardening-profile settlement state"
"revenue-event persistence is atomic with hardening-profile settlement state",
"RFQ executions preserve a deterministic venue-signed source binding to signed RFQ, quote and acceptance records"
],
"schema": "entity-v3-eep-conformance-manifest-v1",
"snapshot_sha256": "00b066155090b7612191852293429d00d76c996ccf00c122fc1f549f19f3cf53",
"snapshot_sha256": "65224aa97bde5456c4079097a37284ce6e023f3e1c635f25456683c74e3df91a",
"status": "BTG_INTERNAL_QUALIFIED_RELEASE_COMPONENT",
"version": "3.0.0",
"working_tree_snapshot": false
Expand Down
13 changes: 7 additions & 6 deletions ENTITY_V3_EOPP_HARDENING_MANIFEST.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@
"files": [
{
"path": "src/33_Economic_Participation/economic_participation.py",
"sha256": "3d805ab601bbf46001175796b601c3c66190c704408f86beb21f942f1de6a9d5"
"sha256": "493268dcc2a2d4564172cb7039e74861bfe63d93734e8b4a1cb70b97dc390d66"
},
{
"path": "src/33_Economic_Participation/btg_deployment.py",
"sha256": "e6ecfe044ea3d5516f3fe3649252b0c23d3ec22a252e4cb8fc98880c98d1ff26"
},
{
"path": "tests/test_v3_economic_participation.py",
"sha256": "35c376010c209108aa0c314f531c06739c8af929c0bfea6af1753d5452f1c093"
"sha256": "f181089a2ed983dca3dfe1fb6f2a4690b4e285db9ed5992006a4477ef285be4b"
},
{
"path": "protocol/v3/ENTITY_ORIGINATOR_PARTICIPATION_PROFILE.md",
Expand All @@ -44,7 +44,8 @@
"event_and_obligation_trade_reconciliation",
"provider_receivable_without_payer_private_key",
"derivative_currency_binding",
"expanded_normative_record_schema"
"expanded_normative_record_schema",
"rfq_signed_source_participation_capture"
],
"invariants": {
"cryptocurrency_required": false,
Expand All @@ -55,16 +56,16 @@
},
"preserved_sealed_manifest_sha256": "7dc3dcd40e69dff30c615e01ecea32a96ea81243a123f108167b3fd6d390ad66",
"schema": "entity-v3-eopp-hardening-manifest-v1",
"snapshot_sha256": "6f787cf66a98f05eb9d43f5b2ef4d9ac94502cb9e084707ce060d146450a03a6",
"snapshot_sha256": "7f95bac570b5091346c2fa09a745e422e7b0449d8cf184d77c98ec4d65fdf503",
"status": "BTG_INTERNAL_QUALIFIED_RELEASE_COMPONENT",
"validation": {
"complete_active_tree": {
"passed": 90,
"total": 90
},
"targeted_eopp": {
"passed": 20,
"total": 20
"passed": 24,
"total": 24
}
},
"version": "3.0.0",
Expand Down
8 changes: 4 additions & 4 deletions ENTITY_V3_MARKET_RECOVERY_MANIFEST.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"files": [
{
"path": "src/34_Market_Recovery/market_recovery.py",
"sha256": "97d084fdcece2289a5860e6a16007c40f39cd95f27693c961d702fdd1b388cd9"
"sha256": "7a96f1e44b7910e7c1560074591c5a5dba208bd66d5e10702d828bd57b35e606"
},
{
"path": "tests/test_v3_market_recovery.py",
Expand All @@ -27,11 +27,11 @@
},
{
"path": "ENTITY_V3_EEP_CONFORMANCE_MANIFEST.json",
"sha256": "07700ba28c78f9d7d5c65f946fc5a320f05f32918721f0e9efda75f054d34053"
"sha256": "aa7dd20a8d396084ead3b677eda0251912cb7ccaf8a857bd54d1df84ec7679d1"
},
{
"path": "ENTITY_V3_EOPP_HARDENING_MANIFEST.json",
"sha256": "ecbb035a6fef8accfd68ca36bd2e7425957420b47c7f387c17dfd84341bdb3c4"
"sha256": "25292ef3320e31243c0155ddf297c5b6908b8a8c4b50993b1c66c3aff8295403"
}
],
"implemented": [
Expand All @@ -49,7 +49,7 @@
"required_trade_revenue_binding_recovery"
],
"schema": "entity-v3-market-recovery-evidence-manifest-v1",
"snapshot_sha256": "6055a9bd4c4a3ae0968bd425dd8245f62a4ce5cd57fbb4399903366667b970de",
"snapshot_sha256": "947a0b9bf2aa60078ec990e28962392d428d4fd751a6e2cfebf4f26378abdfd3",
"status": "BTG_INTERNAL_QUALIFIED_RELEASE_COMPONENT",
"validation": {
"complete_active_tree": {
Expand Down
15 changes: 14 additions & 1 deletion src/31_Profiles/exchange_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,10 @@ def _init(self):
acceptance_id TEXT PRIMARY KEY, rfq_id TEXT NOT NULL, quote_id TEXT NOT NULL,
requester TEXT NOT NULL, nonce TEXT NOT NULL UNIQUE, created_at_ms INTEGER NOT NULL,
received_at_ms INTEGER NOT NULL, signature_json TEXT NOT NULL);
CREATE TABLE IF NOT EXISTS rfq_trade_sources(
trade_id TEXT PRIMARY KEY, rfq_id TEXT NOT NULL, quote_id TEXT NOT NULL,
acceptance_id TEXT NOT NULL, venue_operator TEXT NOT NULL,
created_at_ms INTEGER NOT NULL, signature_json TEXT NOT NULL);
CREATE TABLE IF NOT EXISTS order_cancellations(
cancellation_id TEXT PRIMARY KEY, order_id TEXT NOT NULL, participant TEXT NOT NULL,
nonce TEXT NOT NULL UNIQUE, created_at_ms INTEGER NOT NULL,
Expand Down Expand Up @@ -877,6 +881,15 @@ def _record_signed_quote_acceptance(self, body: dict, signature: dict) -> dict:
buy_stub={"venue_id":rfq["venue_id"],"instrument_id":rfq["instrument_id"],"order_id":None,"participant":buyer}
sell_stub={"order_id":None,"participant":seller}
trade_id=self._execute_trade(db,buy_stub,sell_stub,int(rfq["quantity"]),int(quote["price"]),"RFQ")
venue=db.execute("SELECT * FROM venues WHERE venue_id=? AND status='ACTIVE'",(rfq["venue_id"],)).fetchone()
if not venue: raise KeyError("active RFQ venue missing")
source_created=now_ms()
source_body={"schema":"entity-eep-rfq-execution-source-v1","trade_id":trade_id,"venue_id":rfq["venue_id"],"instrument_id":rfq["instrument_id"],
"rfq_id":body["rfq_id"],"quote_id":body["quote_id"],"acceptance_id":body["acceptance_id"],
"requester":requester,"provider":quote["provider"],"buyer":buyer,"seller":seller,
"quantity":int(rfq["quantity"]),"price":int(quote["price"]),"venue_operator":venue["operator"],"created_at_ms":source_created}
source_sig=self.identity.sign(venue["operator"],source_body)
db.execute("INSERT INTO rfq_trade_sources VALUES(?,?,?,?,?,?,?)",(trade_id,body["rfq_id"],body["quote_id"],body["acceptance_id"],venue["operator"],source_created,json.dumps(source_sig,sort_keys=True)))
db.execute("UPDATE rfqs SET status='ACCEPTED' WHERE rfq_id=?",(body["rfq_id"],))
db.execute("UPDATE quotes SET status='ACCEPTED' WHERE quote_id=?",(body["quote_id"],))
except sqlite3.IntegrityError as exc: raise ValueError("duplicate/replayed RFQ acceptance") from exc
Expand All @@ -899,7 +912,7 @@ def surveillance_alerts(self, venue_id: str) -> list[dict]:

def status(self) -> dict:
with self._db() as db:
tables=("venues","instruments","listings","orders","order_cancellations","trades","clearing","payment_attestations","settlement_verifiers","entitlements","usage","surveillance","rfqs","quotes","rfq_acceptances","revenue_rule_sets","trade_revenue_bindings")
tables=("venues","instruments","listings","orders","order_cancellations","trades","clearing","payment_attestations","settlement_verifiers","entitlements","usage","surveillance","rfqs","quotes","rfq_acceptances","rfq_trade_sources","revenue_rule_sets","trade_revenue_bindings")
counts={name:int(db.execute(f"SELECT COUNT(*) FROM {name}").fetchone()[0]) for name in tables}
return {"schema":"entity-eep-status-v1","profile":"ENTITY_EXCHANGE_PROTOCOL","version":"3.0.0",
"rights_are_traded_not_bytes":True,"venue_neutral":True,"payment_versus_right_transfer":True,
Expand Down
17 changes: 14 additions & 3 deletions src/32_V3_Hardening/exchange_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ def _init(self):
CREATE TABLE IF NOT EXISTS rfqs(rfq_id TEXT PRIMARY KEY,venue_id TEXT,instrument_id TEXT,requester TEXT,side TEXT,quantity INTEGER,expires_at_ms INTEGER,status TEXT,created_at_ms INTEGER,nonce TEXT,received_at_ms INTEGER,signature_json TEXT);
CREATE TABLE IF NOT EXISTS quotes(quote_id TEXT PRIMARY KEY,rfq_id TEXT,provider TEXT,price INTEGER,expires_at_ms INTEGER,status TEXT,created_at_ms INTEGER,nonce TEXT,received_at_ms INTEGER,signature_json TEXT);
CREATE TABLE IF NOT EXISTS rfq_acceptances(acceptance_id TEXT PRIMARY KEY,rfq_id TEXT NOT NULL,quote_id TEXT NOT NULL,requester TEXT NOT NULL,nonce TEXT NOT NULL UNIQUE,created_at_ms INTEGER NOT NULL,received_at_ms INTEGER NOT NULL,signature_json TEXT NOT NULL);
CREATE TABLE IF NOT EXISTS rfq_trade_sources(trade_id TEXT PRIMARY KEY,rfq_id TEXT NOT NULL,quote_id TEXT NOT NULL,acceptance_id TEXT NOT NULL,venue_operator TEXT NOT NULL,created_at_ms INTEGER NOT NULL,signature_json TEXT NOT NULL);
CREATE TABLE IF NOT EXISTS order_cancellations(cancellation_id TEXT PRIMARY KEY,order_id TEXT NOT NULL,participant TEXT NOT NULL,nonce TEXT NOT NULL UNIQUE,created_at_ms INTEGER NOT NULL,received_at_ms INTEGER NOT NULL,signature_json TEXT NOT NULL);
CREATE TABLE IF NOT EXISTS settlement_verifiers(venue_id TEXT NOT NULL,verifier_entity_id TEXT NOT NULL,status TEXT NOT NULL,created_at_ms INTEGER NOT NULL,signature_json TEXT NOT NULL,PRIMARY KEY(venue_id,verifier_entity_id));
CREATE TABLE IF NOT EXISTS payment_attestations(attestation_id TEXT PRIMARY KEY,trade_id TEXT NOT NULL,verifier_entity_id TEXT NOT NULL,settlement_ref TEXT NOT NULL,evidence_sha256 TEXT NOT NULL,nonce TEXT NOT NULL UNIQUE,created_at_ms INTEGER NOT NULL,received_at_ms INTEGER NOT NULL,authority_basis TEXT NOT NULL,signature_json TEXT NOT NULL);
Expand Down Expand Up @@ -575,10 +576,20 @@ def _record_signed_quote_acceptance(self,body,signature):
if available<int(rfq['quantity']): raise PermissionError('RFQ seller lacks unreserved entitlement')
db.execute('INSERT INTO rfq_acceptances VALUES(?,?,?,?,?,?,?,?)',(
body['acceptance_id'],body['rfq_id'],body['quote_id'],requester,str(body['nonce']),created,received,json.dumps(signature,sort_keys=True)))
inst=db.execute('SELECT * FROM instruments WHERE instrument_id=?',(rfq['instrument_id'],)).fetchone(); trade_id=rid('trade3'); amount=int(rfq['quantity'])*int(quote['price'])
db.execute('INSERT INTO trades VALUES(?,?,?,?,?,?,?,?,?,?,?,?)',(trade_id,rfq['venue_id'],rfq['instrument_id'],None,None,buyer,seller,int(rfq['quantity']),int(quote['price']),'RFQ','EXECUTED',now_ms()))
inst=db.execute('SELECT * FROM instruments WHERE instrument_id=?',(rfq['instrument_id'],)).fetchone()
venue=db.execute("SELECT * FROM venues WHERE venue_id=? AND status='ACTIVE'",(rfq['venue_id'],)).fetchone()
if not inst or not venue: raise KeyError('RFQ instrument/venue missing')
trade_id=rid('trade3'); amount=int(rfq['quantity'])*int(quote['price']); trade_created=now_ms()
db.execute('INSERT INTO trades VALUES(?,?,?,?,?,?,?,?,?,?,?,?)',(trade_id,rfq['venue_id'],rfq['instrument_id'],None,None,buyer,seller,int(rfq['quantity']),int(quote['price']),'RFQ','EXECUTED',trade_created))
db.execute('INSERT INTO clearing VALUES(?,?,?,?,?,?,?,?)',(trade_id,buyer,seller,amount,inst['settlement_currency'],'PENDING',None,0))
self._bind_trade_revenue(db,trade_id,rfq['instrument_id'])
source_created=now_ms()
source_body={'schema':'entity-eep-rfq-execution-source-v1','trade_id':trade_id,'venue_id':rfq['venue_id'],'instrument_id':rfq['instrument_id'],
'rfq_id':body['rfq_id'],'quote_id':body['quote_id'],'acceptance_id':body['acceptance_id'],
'requester':requester,'provider':quote['provider'],'buyer':buyer,'seller':seller,
'quantity':int(rfq['quantity']),'price':int(quote['price']),'venue_operator':venue['operator'],'created_at_ms':source_created}
source_sig=self.identity.sign(venue['operator'],source_body)
db.execute('INSERT INTO rfq_trade_sources VALUES(?,?,?,?,?,?,?)',(trade_id,body['rfq_id'],body['quote_id'],body['acceptance_id'],venue['operator'],source_created,json.dumps(source_sig,sort_keys=True)))
db.execute("UPDATE rfqs SET status='ACCEPTED' WHERE rfq_id=?",(body['rfq_id'],)); db.execute("UPDATE quotes SET status='ACCEPTED' WHERE quote_id=?",(body['quote_id'],))
except sqlite3.IntegrityError as exc: raise ValueError('duplicate/replayed RFQ acceptance') from exc
return dict(body,status='EXECUTED',trade_id=trade_id,execution_model='RFQ',received_at_ms=received,signature=signature)
Expand All @@ -596,7 +607,7 @@ def surveillance_alerts(self,venue_id):
return [{**dict(r),'evidence':json.loads(r['evidence_json'])} for r in rows]
def status(self):
with self._db() as db:
tables=('venues','instruments','listings','orders','order_cancellations','trades','clearing','payment_attestations','settlement_verifiers','entitlements','usage','surveillance','rfqs','quotes','rfq_acceptances','revenue_rule_sets','trade_revenue_bindings')
tables=('venues','instruments','listings','orders','order_cancellations','trades','clearing','payment_attestations','settlement_verifiers','entitlements','usage','surveillance','rfqs','quotes','rfq_acceptances','rfq_trade_sources','revenue_rule_sets','trade_revenue_bindings')
counts={name:int(db.execute(f'SELECT COUNT(*) FROM {name}').fetchone()[0]) for name in tables}
return {'schema':'entity-eep-status-v1','profile':'ENTITY_EXCHANGE_PROTOCOL','version':'3.0.0',
'rights_are_traded_not_bytes':True,'venue_neutral':True,'payment_versus_right_transfer':True,
Expand Down
Loading
Loading