parent
42fa4d49d4
commit
adc80eabb0
6 changed files with 293 additions and 10 deletions
@ -0,0 +1,244 @@ |
||||
#!/usr/bin/env python |
||||
# -*- coding: utf-8 -*- |
||||
|
||||
# Copyright (c) 2024 tecnovert |
||||
# Distributed under the MIT software license, see the accompanying |
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php. |
||||
|
||||
|
||||
''' |
||||
0 VARINT int32, int64, uint32, uint64, sint32, sint64, bool, enum |
||||
1 I64 fixed64, sfixed64, double |
||||
2 LEN string, bytes, embedded messages, packed repeated fields |
||||
5 I32 fixed32, sfixed32, float |
||||
|
||||
Don't encode fields of default values. |
||||
When decoding initialise all fields not set from data. |
||||
''' |
||||
|
||||
from basicswap.util.integer import encode_varint, decode_varint |
||||
|
||||
|
||||
class NonProtobufClass(): |
||||
def to_bytes(self) -> bytes: |
||||
rv = bytes() |
||||
|
||||
for field_num, v in self._map.items(): |
||||
field_name, wire_type, field_type = v |
||||
if not hasattr(self, field_name): |
||||
continue |
||||
field_value = getattr(self, field_name) |
||||
tag = (field_num << 3) | wire_type |
||||
if wire_type == 0: |
||||
if field_value == 0: |
||||
continue |
||||
rv += encode_varint(tag) |
||||
rv += encode_varint(field_value) |
||||
elif wire_type == 2: |
||||
if len(field_value) == 0: |
||||
continue |
||||
rv += encode_varint(tag) |
||||
if isinstance(field_value, str): |
||||
field_value = field_value.encode('utf-8') |
||||
rv += encode_varint(len(field_value)) |
||||
rv += field_value |
||||
else: |
||||
raise ValueError(f'Unknown wire_type {wire_type}') |
||||
return rv |
||||
|
||||
def from_bytes(self, b: bytes, init_all: bool = True) -> None: |
||||
max_len: int = len(b) |
||||
o: int = 0 |
||||
while o < max_len: |
||||
tag, lv = decode_varint(b, o) |
||||
o += lv |
||||
wire_type = tag & 7 |
||||
field_num = tag >> 3 |
||||
|
||||
field_name, wire_type_expect, field_type = self._map[field_num] |
||||
if wire_type != wire_type_expect: |
||||
raise ValueError(f'Unexpected wire_type {wire_type} for field {field_num}') |
||||
|
||||
if wire_type == 0: |
||||
field_value, lv = decode_varint(b, o) |
||||
o += lv |
||||
elif wire_type == 2: |
||||
field_len, lv = decode_varint(b, o) |
||||
o += lv |
||||
field_value = b[o: o + field_len] |
||||
o += field_len |
||||
if field_type == 1: |
||||
field_value = field_value.decode('utf-8') |
||||
else: |
||||
raise ValueError(f'Unknown wire_type {wire_type}') |
||||
|
||||
setattr(self, field_name, field_value) |
||||
|
||||
if not init_all: |
||||
return |
||||
# Set default values for missing fields |
||||
for field_num, v in self._map.items(): |
||||
field_name, wire_type, field_type = v |
||||
if hasattr(self, field_name): |
||||
continue |
||||
if wire_type == 0: |
||||
setattr(self, field_name, 0) |
||||
elif wire_type == 2: |
||||
if field_type == 1: |
||||
setattr(self, field_name, str()) |
||||
else: |
||||
setattr(self, field_name, bytes()) |
||||
else: |
||||
raise ValueError(f'Unknown wire_type {wire_type}') |
||||
|
||||
|
||||
class OfferMessage(NonProtobufClass): |
||||
_map = { |
||||
1: ('protocol_version', 0, 0), |
||||
2: ('coin_from', 0, 0), |
||||
3: ('coin_to', 0, 0), |
||||
4: ('amount_from', 0, 0), |
||||
5: ('amount_to', 0, 0), |
||||
6: ('min_bid_amount', 0, 0), |
||||
7: ('time_valid', 0, 0), |
||||
8: ('lock_type', 0, 0), |
||||
9: ('lock_value', 0, 0), |
||||
10: ('swap_type', 0, 0), |
||||
11: ('proof_address', 2, 1), |
||||
12: ('proof_signature', 2, 1), |
||||
13: ('pkhash_seller', 2, 0), |
||||
14: ('secret_hash', 2, 0), |
||||
15: ('fee_rate_from', 0, 0), |
||||
16: ('fee_rate_to', 0, 0), |
||||
17: ('amount_negotiable', 0, 2), |
||||
18: ('rate_negotiable', 0, 2), |
||||
19: ('proof_utxos', 2, 0), |
||||
} |
||||
|
||||
|
||||
class BidMessage(NonProtobufClass): |
||||
_map = { |
||||
1: ('protocol_version', 0, 0), |
||||
2: ('offer_msg_id', 2, 0), |
||||
3: ('time_valid', 0, 0), |
||||
4: ('amount', 0, 0), |
||||
5: ('amount_to', 0, 0), |
||||
6: ('pkhash_buyer', 2, 0), |
||||
7: ('proof_address', 2, 1), |
||||
8: ('proof_signature', 2, 1), |
||||
9: ('proof_utxos', 2, 0), |
||||
10: ('pkhash_buyer_to', 2, 0), |
||||
} |
||||
|
||||
|
||||
class BidAcceptMessage(NonProtobufClass): |
||||
# Step 3, seller -> buyer |
||||
_map = { |
||||
1: ('bid_msg_id', 2, 0), |
||||
2: ('initiate_txid', 2, 0), |
||||
3: ('contract_script', 2, 0), |
||||
4: ('pkhash_seller', 2, 0), |
||||
} |
||||
|
||||
|
||||
class OfferRevokeMessage(NonProtobufClass): |
||||
_map = { |
||||
1: ('offer_msg_id', 2, 0), |
||||
2: ('signature', 2, 0), |
||||
} |
||||
|
||||
|
||||
class BidRejectMessage(NonProtobufClass): |
||||
_map = { |
||||
1: ('bid_msg_id', 2, 0), |
||||
2: ('reject_code', 0, 0), |
||||
} |
||||
|
||||
|
||||
class XmrBidMessage(NonProtobufClass): |
||||
# MSG1L, F -> L |
||||
_map = { |
||||
1: ('protocol_version', 0, 0), |
||||
2: ('offer_msg_id', 2, 0), |
||||
3: ('time_valid', 0, 0), |
||||
4: ('amount', 0, 0), |
||||
5: ('amount_to', 0, 0), |
||||
6: ('pkaf', 2, 0), |
||||
7: ('kbvf', 2, 0), |
||||
8: ('kbsf_dleag', 2, 0), |
||||
9: ('dest_af', 2, 0), |
||||
} |
||||
|
||||
|
||||
class XmrSplitMessage(NonProtobufClass): |
||||
_map = { |
||||
1: ('msg_id', 2, 0), |
||||
2: ('msg_type', 0, 0), |
||||
3: ('sequence', 0, 0), |
||||
4: ('dleag', 2, 0), |
||||
} |
||||
|
||||
|
||||
class XmrBidAcceptMessage(NonProtobufClass): |
||||
_map = { |
||||
1: ('bid_msg_id', 2, 0), |
||||
2: ('pkal', 2, 0), |
||||
3: ('kbvl', 2, 0), |
||||
4: ('kbsl_dleag', 2, 0), |
||||
|
||||
# MSG2F |
||||
5: ('a_lock_tx', 2, 0), |
||||
6: ('a_lock_tx_script', 2, 0), |
||||
7: ('a_lock_refund_tx', 2, 0), |
||||
8: ('a_lock_refund_tx_script', 2, 0), |
||||
9: ('a_lock_refund_spend_tx', 2, 0), |
||||
10: ('al_lock_refund_tx_sig', 2, 0), |
||||
} |
||||
|
||||
|
||||
class XmrBidLockTxSigsMessage(NonProtobufClass): |
||||
# MSG3L |
||||
_map = { |
||||
1: ('bid_msg_id', 2, 0), |
||||
2: ('af_lock_refund_spend_tx_esig', 2, 0), |
||||
3: ('af_lock_refund_tx_sig', 2, 0), |
||||
} |
||||
|
||||
|
||||
class XmrBidLockSpendTxMessage(NonProtobufClass): |
||||
# MSG4F |
||||
_map = { |
||||
1: ('bid_msg_id', 2, 0), |
||||
2: ('a_lock_spend_tx', 2, 0), |
||||
3: ('kal_sig', 2, 0), |
||||
} |
||||
|
||||
|
||||
class XmrBidLockReleaseMessage(NonProtobufClass): |
||||
# MSG5F |
||||
_map = { |
||||
1: ('bid_msg_id', 2, 0), |
||||
2: ('al_lock_spend_tx_esig', 2, 0), |
||||
} |
||||
|
||||
|
||||
class ADSBidIntentMessage(NonProtobufClass): |
||||
# L -> F Sent from bidder, construct a reverse bid |
||||
_map = { |
||||
1: ('protocol_version', 0, 0), |
||||
2: ('offer_msg_id', 2, 0), |
||||
3: ('time_valid', 0, 0), |
||||
4: ('amount_from', 0, 0), |
||||
5: ('amount_to', 0, 0), |
||||
} |
||||
|
||||
|
||||
class ADSBidIntentAcceptMessage(NonProtobufClass): |
||||
# F -> L Sent from offerer, construct a reverse bid |
||||
_map = { |
||||
1: ('bid_msg_id', 2, 0), |
||||
2: ('pkaf', 2, 0), |
||||
3: ('kbvf', 2, 0), |
||||
4: ('kbsf_dleag', 2, 0), |
||||
5: ('dest_af', 2, 0), |
||||
} |
Loading…
Reference in new issue