mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-02-05 04:10:58 +00:00
chore(common): Add GetNonce, Nonce and TxAckPaymentRequest message.
[no changelog]
This commit is contained in:
parent
27d5bf1573
commit
0959947a88
@ -209,6 +209,7 @@ message SignTx {
|
||||
* @next TxAckPrevInput
|
||||
* @next TxAckPrevOutput
|
||||
* @next TxAckPrevExtraData
|
||||
* @next TxAckPaymentRequest
|
||||
*/
|
||||
message TxRequest {
|
||||
optional RequestType request_type = 1; // what should be filled in TxAck message?
|
||||
@ -225,6 +226,7 @@ message TxRequest {
|
||||
TXEXTRADATA = 4;
|
||||
TXORIGINPUT = 5;
|
||||
TXORIGOUTPUT = 6;
|
||||
TXPAYMENTREQ = 7;
|
||||
}
|
||||
/**
|
||||
* Structure representing request details
|
||||
@ -326,6 +328,7 @@ message TxAck {
|
||||
// optional uint32 block_height_bip115 = 9; // BIP-115 support dropped
|
||||
optional bytes orig_hash = 10; // tx_hash of the original transaction where this output was present (used when creating a replacement transaction)
|
||||
optional uint32 orig_index = 11; // index of the output in the original transaction (used when creating a replacement transaction)
|
||||
optional uint32 payment_req_index = 12; // index of the PaymentRequest containing this output
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -369,6 +372,7 @@ message TxOutput {
|
||||
reserved 7, 8, 9; // fields which are in use, or have been in the past, in TxOutputType
|
||||
optional bytes orig_hash = 10; // tx_hash of the original transaction where this output was present (used when creating a replacement transaction)
|
||||
optional uint32 orig_index = 11; // index of the output in the original transaction (used when creating a replacement transaction)
|
||||
optional uint32 payment_req_index = 12; // index of the PaymentRequest containing this output
|
||||
}
|
||||
|
||||
/** Data type for metadata about previous transaction which contains the UTXO being spent.
|
||||
@ -414,6 +418,39 @@ message PrevOutput {
|
||||
optional uint32 decred_script_version = 3; // only for Decred
|
||||
}
|
||||
|
||||
/** Data type of a payment request for a set of outputs.
|
||||
* @next TxRequest
|
||||
*/
|
||||
message TxAckPaymentRequest {
|
||||
optional bytes nonce = 1; // the nonce used in the signature computation
|
||||
required string recipient_name = 2; // merchant's name or coordinator's name in case of CoinJoin
|
||||
repeated PaymentRequestMemo memos = 3; // any memos that were signed as part of the request
|
||||
optional uint64 amount = 4; // the sum of the external output amounts requested, required for non-CoinJoin
|
||||
required bytes signature = 5; // the trusted party's signature of the paymentRequestDigest
|
||||
|
||||
message PaymentRequestMemo {
|
||||
optional TextMemo text_memo = 1;
|
||||
optional RefundMemo refund_memo = 2;
|
||||
optional CoinPurchaseMemo coin_purchase_memo = 3;
|
||||
}
|
||||
|
||||
message TextMemo {
|
||||
required string text = 1; // plain-text note explaining the purpose of the payment request
|
||||
}
|
||||
|
||||
message RefundMemo {
|
||||
required string address = 1; // the address where the payment should be refunded if necessary
|
||||
required bytes mac = 2; // the MAC returned by GetAddress
|
||||
}
|
||||
|
||||
message CoinPurchaseMemo {
|
||||
required uint32 coin_type = 1; // the SLIP-0044 coin type of the address
|
||||
required string amount = 2; // the amount the address will receive as a human-readable string including units, e.g. "0.025 BTC"
|
||||
required string address = 3; // the address where the coin purchase will be delivered
|
||||
required bytes mac = 4; // the MAC returned by GetAddress
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request: Data about input to be signed.
|
||||
* Wire-alias of TxAck.
|
||||
|
@ -421,3 +421,19 @@ message CancelAuthorization {
|
||||
*/
|
||||
message RebootToBootloader {
|
||||
}
|
||||
|
||||
/**
|
||||
* Request: Ask device to generate a random nonce and store it in the session's cache
|
||||
* @start
|
||||
* @next Nonce
|
||||
*/
|
||||
message GetNonce {
|
||||
}
|
||||
|
||||
/**
|
||||
* Response: Contains a random nonce
|
||||
* @end
|
||||
*/
|
||||
message Nonce {
|
||||
required bytes nonce = 1; // a 32-byte random value generated by Trezor
|
||||
}
|
||||
|
@ -96,6 +96,8 @@ enum MessageType {
|
||||
MessageType_ButtonRequest = 26 [(bitcoin_only) = true, (wire_out) = true];
|
||||
MessageType_ButtonAck = 27 [(bitcoin_only) = true, (wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true];
|
||||
MessageType_ApplyFlags = 28 [(bitcoin_only) = true, (wire_in) = true];
|
||||
MessageType_GetNonce = 31 [(bitcoin_only) = true, (wire_in) = true];
|
||||
MessageType_Nonce = 33 [(bitcoin_only) = true, (wire_out) = true];
|
||||
MessageType_BackupDevice = 34 [(bitcoin_only) = true, (wire_in) = true];
|
||||
MessageType_EntropyRequest = 35 [(bitcoin_only) = true, (wire_out) = true];
|
||||
MessageType_EntropyAck = 36 [(bitcoin_only) = true, (wire_in) = true];
|
||||
@ -136,6 +138,7 @@ enum MessageType {
|
||||
MessageType_TxAck = 22 [(bitcoin_only) = true, (wire_in) = true];
|
||||
MessageType_GetAddress = 29 [(bitcoin_only) = true, (wire_in) = true];
|
||||
MessageType_Address = 30 [(bitcoin_only) = true, (wire_out) = true];
|
||||
MessageType_TxAckPaymentRequest = 37 [(wire_in) = true];
|
||||
MessageType_SignMessage = 38 [(bitcoin_only) = true, (wire_in) = true];
|
||||
MessageType_VerifyMessage = 39 [(bitcoin_only) = true, (wire_in) = true];
|
||||
MessageType_MessageSignature = 40 [(bitcoin_only) = true, (wire_out) = true];
|
||||
|
@ -23,6 +23,8 @@ ApplySettings = 25
|
||||
ButtonRequest = 26
|
||||
ButtonAck = 27
|
||||
ApplyFlags = 28
|
||||
GetNonce = 31
|
||||
Nonce = 33
|
||||
BackupDevice = 34
|
||||
EntropyRequest = 35
|
||||
EntropyAck = 36
|
||||
@ -86,6 +88,7 @@ if not utils.BITCOIN_ONLY:
|
||||
SetU2FCounter = 63
|
||||
GetNextU2FCounter = 80
|
||||
NextU2FCounter = 81
|
||||
TxAckPaymentRequest = 37
|
||||
EthereumGetPublicKey = 450
|
||||
EthereumPublicKey = 451
|
||||
EthereumGetAddress = 56
|
||||
|
@ -9,3 +9,4 @@ TXFINISHED = 3
|
||||
TXEXTRADATA = 4
|
||||
TXORIGINPUT = 5
|
||||
TXORIGOUTPUT = 6
|
||||
TXPAYMENTREQ = 7
|
||||
|
@ -23,6 +23,8 @@ if TYPE_CHECKING:
|
||||
ButtonRequest = 26
|
||||
ButtonAck = 27
|
||||
ApplyFlags = 28
|
||||
GetNonce = 31
|
||||
Nonce = 33
|
||||
BackupDevice = 34
|
||||
EntropyRequest = 35
|
||||
EntropyAck = 36
|
||||
@ -55,6 +57,7 @@ if TYPE_CHECKING:
|
||||
TxAck = 22
|
||||
GetAddress = 29
|
||||
Address = 30
|
||||
TxAckPaymentRequest = 37
|
||||
SignMessage = 38
|
||||
VerifyMessage = 39
|
||||
MessageSignature = 40
|
||||
@ -324,6 +327,7 @@ if TYPE_CHECKING:
|
||||
TXEXTRADATA = 4
|
||||
TXORIGINPUT = 5
|
||||
TXORIGOUTPUT = 6
|
||||
TXPAYMENTREQ = 7
|
||||
|
||||
class CardanoDerivationType(IntEnum):
|
||||
LEDGER = 0
|
||||
|
@ -683,6 +683,7 @@ if TYPE_CHECKING:
|
||||
op_return_data: "bytes | None"
|
||||
orig_hash: "bytes | None"
|
||||
orig_index: "int | None"
|
||||
payment_req_index: "int | None"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -695,6 +696,7 @@ if TYPE_CHECKING:
|
||||
op_return_data: "bytes | None" = None,
|
||||
orig_hash: "bytes | None" = None,
|
||||
orig_index: "int | None" = None,
|
||||
payment_req_index: "int | None" = None,
|
||||
) -> None:
|
||||
pass
|
||||
|
||||
@ -772,6 +774,28 @@ if TYPE_CHECKING:
|
||||
def is_type_of(cls, msg: protobuf.MessageType) -> TypeGuard["PrevOutput"]:
|
||||
return isinstance(msg, cls)
|
||||
|
||||
class TxAckPaymentRequest(protobuf.MessageType):
|
||||
nonce: "bytes | None"
|
||||
recipient_name: "str"
|
||||
memos: "list[PaymentRequestMemo]"
|
||||
amount: "int | None"
|
||||
signature: "bytes"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
recipient_name: "str",
|
||||
signature: "bytes",
|
||||
memos: "list[PaymentRequestMemo] | None" = None,
|
||||
nonce: "bytes | None" = None,
|
||||
amount: "int | None" = None,
|
||||
) -> None:
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def is_type_of(cls, msg: protobuf.MessageType) -> TypeGuard["TxAckPaymentRequest"]:
|
||||
return isinstance(msg, cls)
|
||||
|
||||
class TxAckInput(protobuf.MessageType):
|
||||
tx: "TxAckInputWrapper"
|
||||
|
||||
@ -978,6 +1002,74 @@ if TYPE_CHECKING:
|
||||
def is_type_of(cls, msg: protobuf.MessageType) -> TypeGuard["TxRequestSerializedType"]:
|
||||
return isinstance(msg, cls)
|
||||
|
||||
class PaymentRequestMemo(protobuf.MessageType):
|
||||
text_memo: "TextMemo | None"
|
||||
refund_memo: "RefundMemo | None"
|
||||
coin_purchase_memo: "CoinPurchaseMemo | None"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
text_memo: "TextMemo | None" = None,
|
||||
refund_memo: "RefundMemo | None" = None,
|
||||
coin_purchase_memo: "CoinPurchaseMemo | None" = None,
|
||||
) -> None:
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def is_type_of(cls, msg: protobuf.MessageType) -> TypeGuard["PaymentRequestMemo"]:
|
||||
return isinstance(msg, cls)
|
||||
|
||||
class TextMemo(protobuf.MessageType):
|
||||
text: "str"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
text: "str",
|
||||
) -> None:
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def is_type_of(cls, msg: protobuf.MessageType) -> TypeGuard["TextMemo"]:
|
||||
return isinstance(msg, cls)
|
||||
|
||||
class RefundMemo(protobuf.MessageType):
|
||||
address: "str"
|
||||
mac: "bytes"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
address: "str",
|
||||
mac: "bytes",
|
||||
) -> None:
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def is_type_of(cls, msg: protobuf.MessageType) -> TypeGuard["RefundMemo"]:
|
||||
return isinstance(msg, cls)
|
||||
|
||||
class CoinPurchaseMemo(protobuf.MessageType):
|
||||
coin_type: "int"
|
||||
amount: "str"
|
||||
address: "str"
|
||||
mac: "bytes"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
coin_type: "int",
|
||||
amount: "str",
|
||||
address: "str",
|
||||
mac: "bytes",
|
||||
) -> None:
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def is_type_of(cls, msg: protobuf.MessageType) -> TypeGuard["CoinPurchaseMemo"]:
|
||||
return isinstance(msg, cls)
|
||||
|
||||
class TxAckInputWrapper(protobuf.MessageType):
|
||||
input: "TxInput"
|
||||
|
||||
@ -2258,6 +2350,26 @@ if TYPE_CHECKING:
|
||||
def is_type_of(cls, msg: protobuf.MessageType) -> TypeGuard["RebootToBootloader"]:
|
||||
return isinstance(msg, cls)
|
||||
|
||||
class GetNonce(protobuf.MessageType):
|
||||
|
||||
@classmethod
|
||||
def is_type_of(cls, msg: protobuf.MessageType) -> TypeGuard["GetNonce"]:
|
||||
return isinstance(msg, cls)
|
||||
|
||||
class Nonce(protobuf.MessageType):
|
||||
nonce: "bytes"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
nonce: "bytes",
|
||||
) -> None:
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def is_type_of(cls, msg: protobuf.MessageType) -> TypeGuard["Nonce"]:
|
||||
return isinstance(msg, cls)
|
||||
|
||||
class DebugLinkDecision(protobuf.MessageType):
|
||||
button: "DebugButton | None"
|
||||
swipe: "DebugSwipeDirection | None"
|
||||
|
@ -5,8 +5,8 @@ endif
|
||||
SKIPPED_MESSAGES := Binance Cardano DebugMonero Eos Monero Ontology Ripple SdProtect Tezos WebAuthn \
|
||||
DebugLinkRecordScreen DebugLinkReseedRandom DebugLinkShowText DebugLinkEraseSdCard DebugLinkWatchLayout \
|
||||
GetOwnershipProof OwnershipProof GetOwnershipId OwnershipId AuthorizeCoinJoin DoPreauthorized \
|
||||
CancelAuthorization DebugLinkLayout \
|
||||
TxAckInput TxAckOutput TxAckPrev \
|
||||
CancelAuthorization DebugLinkLayout GetNonce \
|
||||
TxAckInput TxAckOutput TxAckPrev TxAckPaymentRequest \
|
||||
EthereumSignTypedData EthereumTypedDataStructRequest EthereumTypedDataStructAck \
|
||||
EthereumTypedDataValueRequest EthereumTypedDataValueAck
|
||||
|
||||
|
@ -83,3 +83,5 @@ GetOwnershipId skip_message:true
|
||||
OwnershipId skip_message:true
|
||||
GetOwnershipProof skip_message:true
|
||||
OwnershipProof skip_message:true
|
||||
TxAckPaymentRequest skip_message:true
|
||||
PaymentRequestMemo skip_message:true
|
||||
|
@ -33,3 +33,5 @@ RecoveryDevice.language max_size:17
|
||||
RecoveryDevice.label max_size:33
|
||||
|
||||
WordAck.word max_size:12
|
||||
|
||||
Nonce.nonce max_size:32
|
||||
|
@ -48,6 +48,8 @@ class MessageType(IntEnum):
|
||||
ButtonRequest = 26
|
||||
ButtonAck = 27
|
||||
ApplyFlags = 28
|
||||
GetNonce = 31
|
||||
Nonce = 33
|
||||
BackupDevice = 34
|
||||
EntropyRequest = 35
|
||||
EntropyAck = 36
|
||||
@ -80,6 +82,7 @@ class MessageType(IntEnum):
|
||||
TxAck = 22
|
||||
GetAddress = 29
|
||||
Address = 30
|
||||
TxAckPaymentRequest = 37
|
||||
SignMessage = 38
|
||||
VerifyMessage = 39
|
||||
MessageSignature = 40
|
||||
@ -340,6 +343,7 @@ class RequestType(IntEnum):
|
||||
TXEXTRADATA = 4
|
||||
TXORIGINPUT = 5
|
||||
TXORIGOUTPUT = 6
|
||||
TXPAYMENTREQ = 7
|
||||
|
||||
|
||||
class CardanoDerivationType(IntEnum):
|
||||
@ -1284,6 +1288,7 @@ class TxOutput(protobuf.MessageType):
|
||||
6: protobuf.Field("op_return_data", "bytes", repeated=False, required=False),
|
||||
10: protobuf.Field("orig_hash", "bytes", repeated=False, required=False),
|
||||
11: protobuf.Field("orig_index", "uint32", repeated=False, required=False),
|
||||
12: protobuf.Field("payment_req_index", "uint32", repeated=False, required=False),
|
||||
}
|
||||
|
||||
def __init__(
|
||||
@ -1297,6 +1302,7 @@ class TxOutput(protobuf.MessageType):
|
||||
op_return_data: Optional["bytes"] = None,
|
||||
orig_hash: Optional["bytes"] = None,
|
||||
orig_index: Optional["int"] = None,
|
||||
payment_req_index: Optional["int"] = None,
|
||||
) -> None:
|
||||
self.address_n: Sequence["int"] = address_n if address_n is not None else []
|
||||
self.amount = amount
|
||||
@ -1306,6 +1312,7 @@ class TxOutput(protobuf.MessageType):
|
||||
self.op_return_data = op_return_data
|
||||
self.orig_hash = orig_hash
|
||||
self.orig_index = orig_index
|
||||
self.payment_req_index = payment_req_index
|
||||
|
||||
|
||||
class PrevTx(protobuf.MessageType):
|
||||
@ -1392,6 +1399,32 @@ class PrevOutput(protobuf.MessageType):
|
||||
self.decred_script_version = decred_script_version
|
||||
|
||||
|
||||
class TxAckPaymentRequest(protobuf.MessageType):
|
||||
MESSAGE_WIRE_TYPE = 37
|
||||
FIELDS = {
|
||||
1: protobuf.Field("nonce", "bytes", repeated=False, required=False),
|
||||
2: protobuf.Field("recipient_name", "string", repeated=False, required=True),
|
||||
3: protobuf.Field("memos", "PaymentRequestMemo", repeated=True, required=False),
|
||||
4: protobuf.Field("amount", "uint64", repeated=False, required=False),
|
||||
5: protobuf.Field("signature", "bytes", repeated=False, required=True),
|
||||
}
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
recipient_name: "str",
|
||||
signature: "bytes",
|
||||
memos: Optional[Sequence["PaymentRequestMemo"]] = None,
|
||||
nonce: Optional["bytes"] = None,
|
||||
amount: Optional["int"] = None,
|
||||
) -> None:
|
||||
self.memos: Sequence["PaymentRequestMemo"] = memos if memos is not None else []
|
||||
self.recipient_name = recipient_name
|
||||
self.signature = signature
|
||||
self.nonce = nonce
|
||||
self.amount = amount
|
||||
|
||||
|
||||
class TxAckInput(protobuf.MessageType):
|
||||
MESSAGE_WIRE_TYPE = 22
|
||||
FIELDS = {
|
||||
@ -1760,6 +1793,7 @@ class TxOutputType(protobuf.MessageType):
|
||||
6: protobuf.Field("op_return_data", "bytes", repeated=False, required=False),
|
||||
10: protobuf.Field("orig_hash", "bytes", repeated=False, required=False),
|
||||
11: protobuf.Field("orig_index", "uint32", repeated=False, required=False),
|
||||
12: protobuf.Field("payment_req_index", "uint32", repeated=False, required=False),
|
||||
}
|
||||
|
||||
def __init__(
|
||||
@ -1773,6 +1807,7 @@ class TxOutputType(protobuf.MessageType):
|
||||
op_return_data: Optional["bytes"] = None,
|
||||
orig_hash: Optional["bytes"] = None,
|
||||
orig_index: Optional["int"] = None,
|
||||
payment_req_index: Optional["int"] = None,
|
||||
) -> None:
|
||||
self.address_n: Sequence["int"] = address_n if address_n is not None else []
|
||||
self.amount = amount
|
||||
@ -1782,6 +1817,81 @@ class TxOutputType(protobuf.MessageType):
|
||||
self.op_return_data = op_return_data
|
||||
self.orig_hash = orig_hash
|
||||
self.orig_index = orig_index
|
||||
self.payment_req_index = payment_req_index
|
||||
|
||||
|
||||
class PaymentRequestMemo(protobuf.MessageType):
|
||||
MESSAGE_WIRE_TYPE = None
|
||||
FIELDS = {
|
||||
1: protobuf.Field("text_memo", "TextMemo", repeated=False, required=False),
|
||||
2: protobuf.Field("refund_memo", "RefundMemo", repeated=False, required=False),
|
||||
3: protobuf.Field("coin_purchase_memo", "CoinPurchaseMemo", repeated=False, required=False),
|
||||
}
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
text_memo: Optional["TextMemo"] = None,
|
||||
refund_memo: Optional["RefundMemo"] = None,
|
||||
coin_purchase_memo: Optional["CoinPurchaseMemo"] = None,
|
||||
) -> None:
|
||||
self.text_memo = text_memo
|
||||
self.refund_memo = refund_memo
|
||||
self.coin_purchase_memo = coin_purchase_memo
|
||||
|
||||
|
||||
class TextMemo(protobuf.MessageType):
|
||||
MESSAGE_WIRE_TYPE = None
|
||||
FIELDS = {
|
||||
1: protobuf.Field("text", "string", repeated=False, required=True),
|
||||
}
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
text: "str",
|
||||
) -> None:
|
||||
self.text = text
|
||||
|
||||
|
||||
class RefundMemo(protobuf.MessageType):
|
||||
MESSAGE_WIRE_TYPE = None
|
||||
FIELDS = {
|
||||
1: protobuf.Field("address", "string", repeated=False, required=True),
|
||||
2: protobuf.Field("mac", "bytes", repeated=False, required=True),
|
||||
}
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
address: "str",
|
||||
mac: "bytes",
|
||||
) -> None:
|
||||
self.address = address
|
||||
self.mac = mac
|
||||
|
||||
|
||||
class CoinPurchaseMemo(protobuf.MessageType):
|
||||
MESSAGE_WIRE_TYPE = None
|
||||
FIELDS = {
|
||||
1: protobuf.Field("coin_type", "uint32", repeated=False, required=True),
|
||||
2: protobuf.Field("amount", "string", repeated=False, required=True),
|
||||
3: protobuf.Field("address", "string", repeated=False, required=True),
|
||||
4: protobuf.Field("mac", "bytes", repeated=False, required=True),
|
||||
}
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
coin_type: "int",
|
||||
amount: "str",
|
||||
address: "str",
|
||||
mac: "bytes",
|
||||
) -> None:
|
||||
self.coin_type = coin_type
|
||||
self.amount = amount
|
||||
self.address = address
|
||||
self.mac = mac
|
||||
|
||||
|
||||
class TxAckInputWrapper(protobuf.MessageType):
|
||||
@ -3532,6 +3642,24 @@ class RebootToBootloader(protobuf.MessageType):
|
||||
MESSAGE_WIRE_TYPE = 87
|
||||
|
||||
|
||||
class GetNonce(protobuf.MessageType):
|
||||
MESSAGE_WIRE_TYPE = 31
|
||||
|
||||
|
||||
class Nonce(protobuf.MessageType):
|
||||
MESSAGE_WIRE_TYPE = 33
|
||||
FIELDS = {
|
||||
1: protobuf.Field("nonce", "bytes", repeated=False, required=True),
|
||||
}
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
nonce: "bytes",
|
||||
) -> None:
|
||||
self.nonce = nonce
|
||||
|
||||
|
||||
class DebugLinkDecision(protobuf.MessageType):
|
||||
MESSAGE_WIRE_TYPE = 100
|
||||
FIELDS = {
|
||||
|
Loading…
Reference in New Issue
Block a user