mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-22 14:28:07 +00:00
nem: refactor serialization code
This commit is contained in:
parent
e3caf14c43
commit
2ac59892b7
244
nem.c
244
nem.c
@ -30,6 +30,16 @@
|
|||||||
#include "sha3.h"
|
#include "sha3.h"
|
||||||
#include "memzero.h"
|
#include "memzero.h"
|
||||||
|
|
||||||
|
#define CAN_WRITE(NEEDED) ((ctx->offset + (NEEDED)) <= ctx->size)
|
||||||
|
|
||||||
|
#define SERIALIZE_U32(DATA) \
|
||||||
|
do { if (!nem_write_u32(ctx, (DATA))) return false; } while (0)
|
||||||
|
#define SERIALIZE_U64(DATA) \
|
||||||
|
do { if (!nem_write_u64(ctx, (DATA))) return false; } while (0)
|
||||||
|
#define SERIALIZE_TAGGED(DATA, LENGTH) \
|
||||||
|
do { if (!nem_write_tagged(ctx, (DATA), (LENGTH))) return false; } while (0)
|
||||||
|
|
||||||
|
|
||||||
const char *nem_network_name(uint8_t network) {
|
const char *nem_network_name(uint8_t network) {
|
||||||
switch (network) {
|
switch (network) {
|
||||||
case NEM_NETWORK_MAINNET:
|
case NEM_NETWORK_MAINNET:
|
||||||
@ -43,39 +53,49 @@ const char *nem_network_name(uint8_t network) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void nem_write_u32(nem_transaction_ctx *ctx, uint32_t data) {
|
static inline bool nem_write_checked(nem_transaction_ctx *ctx, const uint8_t *data, uint32_t length) {
|
||||||
|
if (!CAN_WRITE(length)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&ctx->buffer[ctx->offset], data, length);
|
||||||
|
ctx->offset += length;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool nem_write_u32(nem_transaction_ctx *ctx, uint32_t data) {
|
||||||
|
if (!CAN_WRITE(4)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
ctx->buffer[ctx->offset++] = (data >> 0) & 0xff;
|
ctx->buffer[ctx->offset++] = (data >> 0) & 0xff;
|
||||||
ctx->buffer[ctx->offset++] = (data >> 8) & 0xff;
|
ctx->buffer[ctx->offset++] = (data >> 8) & 0xff;
|
||||||
ctx->buffer[ctx->offset++] = (data >> 16) & 0xff;
|
ctx->buffer[ctx->offset++] = (data >> 16) & 0xff;
|
||||||
ctx->buffer[ctx->offset++] = (data >> 24) & 0xff;
|
ctx->buffer[ctx->offset++] = (data >> 24) & 0xff;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void nem_write_u64(nem_transaction_ctx *ctx, uint64_t data) {
|
static inline bool nem_write_u64(nem_transaction_ctx *ctx, uint64_t data) {
|
||||||
nem_write_u32(ctx, (data >> 0) & 0xffffffff);
|
SERIALIZE_U32((data >> 0) & 0xffffffff);
|
||||||
nem_write_u32(ctx, (data >> 32) & 0xffffffff);
|
SERIALIZE_U32((data >> 32) & 0xffffffff);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void nem_write(nem_transaction_ctx *ctx, const uint8_t *data, uint32_t length) {
|
static inline bool nem_write_tagged(nem_transaction_ctx *ctx, const uint8_t *data, uint32_t length) {
|
||||||
nem_write_u32(ctx, length);
|
SERIALIZE_U32(length);
|
||||||
|
|
||||||
memcpy(&ctx->buffer[ctx->offset], data, length);
|
return nem_write_checked(ctx, data, length);
|
||||||
ctx->offset += length;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool nem_can_write(nem_transaction_ctx *ctx, size_t needed) {
|
|
||||||
return (ctx->offset + needed) <= ctx->size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool nem_write_mosaic_str(nem_transaction_ctx *ctx, const char *name, const char *value) {
|
static inline bool nem_write_mosaic_str(nem_transaction_ctx *ctx, const char *name, const char *value) {
|
||||||
uint32_t name_length = strlen(name);
|
uint32_t name_length = strlen(name);
|
||||||
uint32_t value_length = strlen(value);
|
uint32_t value_length = strlen(value);
|
||||||
|
|
||||||
#define NEM_SERIALIZE \
|
SERIALIZE_U32(sizeof(uint32_t) + name_length + sizeof(uint32_t) + value_length);
|
||||||
serialize_u32(sizeof(uint32_t) + name_length + sizeof(uint32_t) + value_length) \
|
SERIALIZE_TAGGED((const uint8_t *) name, name_length);
|
||||||
serialize_write((uint8_t *) name, name_length) \
|
SERIALIZE_TAGGED((const uint8_t *) value, value_length);
|
||||||
serialize_write((uint8_t *) value, value_length)
|
|
||||||
|
|
||||||
#include "nem_serialize.h"
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -178,15 +198,12 @@ bool nem_transaction_write_common(nem_transaction_ctx *ctx,
|
|||||||
uint64_t fee,
|
uint64_t fee,
|
||||||
uint32_t deadline) {
|
uint32_t deadline) {
|
||||||
|
|
||||||
#define NEM_SERIALIZE \
|
SERIALIZE_U32(type);
|
||||||
serialize_u32(type) \
|
SERIALIZE_U32(version);
|
||||||
serialize_u32(version) \
|
SERIALIZE_U32(timestamp);
|
||||||
serialize_u32(timestamp) \
|
SERIALIZE_TAGGED(signer, sizeof(ed25519_public_key));
|
||||||
serialize_write(signer, sizeof(ed25519_public_key)) \
|
SERIALIZE_U64(fee);
|
||||||
serialize_u64(fee) \
|
SERIALIZE_U32(deadline);
|
||||||
serialize_u32(deadline)
|
|
||||||
|
|
||||||
#include "nem_serialize.h"
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -221,36 +238,20 @@ bool nem_transaction_create_transfer(nem_transaction_ctx *ctx,
|
|||||||
deadline);
|
deadline);
|
||||||
if (!ret) return false;
|
if (!ret) return false;
|
||||||
|
|
||||||
#define NEM_SERIALIZE \
|
SERIALIZE_TAGGED((const uint8_t *) recipient, NEM_ADDRESS_SIZE);
|
||||||
serialize_write((uint8_t *) recipient, NEM_ADDRESS_SIZE) \
|
SERIALIZE_U64(amount);
|
||||||
serialize_u64(amount)
|
|
||||||
|
|
||||||
#include "nem_serialize.h"
|
|
||||||
|
|
||||||
if (length) {
|
if (length) {
|
||||||
|
SERIALIZE_U32(sizeof(uint32_t) + sizeof(uint32_t) + length);
|
||||||
#define NEM_SERIALIZE \
|
SERIALIZE_U32(encrypted ? 0x02 : 0x01);
|
||||||
serialize_u32(sizeof(uint32_t) + sizeof(uint32_t) + length) \
|
SERIALIZE_TAGGED(payload, length);
|
||||||
serialize_u32(encrypted ? 0x02 : 0x01) \
|
|
||||||
serialize_write(payload, length)
|
|
||||||
|
|
||||||
#include "nem_serialize.h"
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
SERIALIZE_U32(0);
|
||||||
#define NEM_SERIALIZE \
|
|
||||||
serialize_u32(0)
|
|
||||||
|
|
||||||
#include "nem_serialize.h"
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mosaics) {
|
if (mosaics) {
|
||||||
|
|
||||||
#define NEM_SERIALIZE \
|
SERIALIZE_U32(mosaics);
|
||||||
serialize_u32(mosaics)
|
|
||||||
|
|
||||||
#include "nem_serialize.h"
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,14 +267,11 @@ bool nem_transaction_write_mosaic(nem_transaction_ctx *ctx,
|
|||||||
size_t mosaic_length = strlen(mosaic);
|
size_t mosaic_length = strlen(mosaic);
|
||||||
size_t identifier_length = sizeof(uint32_t) + namespace_length + sizeof(uint32_t) + mosaic_length;
|
size_t identifier_length = sizeof(uint32_t) + namespace_length + sizeof(uint32_t) + mosaic_length;
|
||||||
|
|
||||||
#define NEM_SERIALIZE \
|
SERIALIZE_U32(sizeof(uint32_t) + sizeof(uint64_t) + identifier_length);
|
||||||
serialize_u32(sizeof(uint32_t) + sizeof(uint64_t) + identifier_length) \
|
SERIALIZE_U32(identifier_length);
|
||||||
serialize_u32(identifier_length) \
|
SERIALIZE_TAGGED((const uint8_t *) namespace, namespace_length);
|
||||||
serialize_write((uint8_t *) namespace, namespace_length) \
|
SERIALIZE_TAGGED((const uint8_t *) mosaic, mosaic_length);
|
||||||
serialize_write((uint8_t *) mosaic, mosaic_length) \
|
SERIALIZE_U64(quantity);
|
||||||
serialize_u64(quantity)
|
|
||||||
|
|
||||||
#include "nem_serialize.h"
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -299,10 +297,7 @@ bool nem_transaction_create_multisig(nem_transaction_ctx *ctx,
|
|||||||
deadline);
|
deadline);
|
||||||
if (!ret) return false;
|
if (!ret) return false;
|
||||||
|
|
||||||
#define NEM_SERIALIZE \
|
SERIALIZE_TAGGED(inner->buffer, inner->offset);
|
||||||
serialize_write(inner->buffer, inner->offset)
|
|
||||||
|
|
||||||
#include "nem_serialize.h"
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -334,12 +329,9 @@ bool nem_transaction_create_multisig_signature(nem_transaction_ctx *ctx,
|
|||||||
uint8_t hash[SHA3_256_DIGEST_LENGTH];
|
uint8_t hash[SHA3_256_DIGEST_LENGTH];
|
||||||
keccak_256(inner->buffer, inner->offset, hash);
|
keccak_256(inner->buffer, inner->offset, hash);
|
||||||
|
|
||||||
#define NEM_SERIALIZE \
|
SERIALIZE_U32(sizeof(uint32_t) + SHA3_256_DIGEST_LENGTH);
|
||||||
serialize_u32(sizeof(uint32_t) + SHA3_256_DIGEST_LENGTH) \
|
SERIALIZE_TAGGED(hash, SHA3_256_DIGEST_LENGTH);
|
||||||
serialize_write(hash, SHA3_256_DIGEST_LENGTH) \
|
SERIALIZE_TAGGED((const uint8_t *) address, NEM_ADDRESS_SIZE);
|
||||||
serialize_write((uint8_t *) address, NEM_ADDRESS_SIZE)
|
|
||||||
|
|
||||||
#include "nem_serialize.h"
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -369,25 +361,15 @@ bool nem_transaction_create_provision_namespace(nem_transaction_ctx *ctx,
|
|||||||
if (!ret) return false;
|
if (!ret) return false;
|
||||||
|
|
||||||
if (parent) {
|
if (parent) {
|
||||||
|
SERIALIZE_TAGGED((const uint8_t *) rental_sink, NEM_ADDRESS_SIZE);
|
||||||
#define NEM_SERIALIZE \
|
SERIALIZE_U64(rental_fee);
|
||||||
serialize_write((uint8_t *) rental_sink, NEM_ADDRESS_SIZE) \
|
SERIALIZE_TAGGED((const uint8_t *) namespace, strlen(namespace));
|
||||||
serialize_u64(rental_fee) \
|
SERIALIZE_TAGGED((const uint8_t *) parent, strlen(parent));
|
||||||
serialize_write((uint8_t *) namespace, strlen(namespace)) \
|
|
||||||
serialize_write((uint8_t *) parent, strlen(parent))
|
|
||||||
|
|
||||||
#include "nem_serialize.h"
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
SERIALIZE_TAGGED((const uint8_t *) rental_sink, NEM_ADDRESS_SIZE);
|
||||||
#define NEM_SERIALIZE \
|
SERIALIZE_U64(rental_fee);
|
||||||
serialize_write((uint8_t *) rental_sink, NEM_ADDRESS_SIZE) \
|
SERIALIZE_TAGGED((const uint8_t *) namespace, strlen(namespace));
|
||||||
serialize_u64(rental_fee) \
|
SERIALIZE_U32(0xffffffff);
|
||||||
serialize_write((uint8_t *) namespace, strlen(namespace)) \
|
|
||||||
serialize_u32(0xffffffff)
|
|
||||||
|
|
||||||
#include "nem_serialize.h"
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -435,16 +417,13 @@ bool nem_transaction_create_mosaic_creation(nem_transaction_ctx *ctx,
|
|||||||
nem_transaction_ctx state;
|
nem_transaction_ctx state;
|
||||||
memcpy(&state, ctx, sizeof(state));
|
memcpy(&state, ctx, sizeof(state));
|
||||||
|
|
||||||
#define NEM_SERIALIZE \
|
SERIALIZE_U32(0);
|
||||||
serialize_u32(0) \
|
SERIALIZE_TAGGED(signer, sizeof(ed25519_public_key));
|
||||||
serialize_write(signer, sizeof(ed25519_public_key)) \
|
SERIALIZE_U32(identifier_length);
|
||||||
serialize_u32(identifier_length) \
|
SERIALIZE_TAGGED((const uint8_t *) namespace, namespace_length);
|
||||||
serialize_write((uint8_t *) namespace, namespace_length) \
|
SERIALIZE_TAGGED((const uint8_t *) mosaic, mosaic_length);
|
||||||
serialize_write((uint8_t *) mosaic, mosaic_length) \
|
SERIALIZE_TAGGED((const uint8_t *) description, strlen(description));
|
||||||
serialize_write((uint8_t *) description, strlen(description)) \
|
SERIALIZE_U32(4); // Number of properties
|
||||||
serialize_u32(4) // Number of properties
|
|
||||||
|
|
||||||
#include "nem_serialize.h"
|
|
||||||
|
|
||||||
if (!nem_write_mosaic_u64(ctx, "divisibility", divisibility)) return false;
|
if (!nem_write_mosaic_u64(ctx, "divisibility", divisibility)) return false;
|
||||||
if (!nem_write_mosaic_u64(ctx, "initialSupply", supply)) return false;
|
if (!nem_write_mosaic_u64(ctx, "initialSupply", supply)) return false;
|
||||||
@ -456,34 +435,22 @@ bool nem_transaction_create_mosaic_creation(nem_transaction_ctx *ctx,
|
|||||||
size_t levy_mosaic_length = strlen(levy_mosaic);
|
size_t levy_mosaic_length = strlen(levy_mosaic);
|
||||||
size_t levy_identifier_length = sizeof(uint32_t) + levy_namespace_length + sizeof(uint32_t) + levy_mosaic_length;
|
size_t levy_identifier_length = sizeof(uint32_t) + levy_namespace_length + sizeof(uint32_t) + levy_mosaic_length;
|
||||||
|
|
||||||
#define NEM_SERIALIZE \
|
SERIALIZE_U32(sizeof(uint32_t) + sizeof(uint32_t) + NEM_ADDRESS_SIZE + sizeof(uint32_t) + levy_identifier_length + sizeof(uint64_t));
|
||||||
serialize_u32(sizeof(uint32_t) + sizeof(uint32_t) + NEM_ADDRESS_SIZE + sizeof(uint32_t) + levy_identifier_length + sizeof(uint64_t)) \
|
SERIALIZE_U32(levy_type);
|
||||||
serialize_u32(levy_type) \
|
SERIALIZE_TAGGED((const uint8_t *) levy_address, NEM_ADDRESS_SIZE);
|
||||||
serialize_write((uint8_t *) levy_address, NEM_ADDRESS_SIZE) \
|
SERIALIZE_U32(levy_identifier_length);
|
||||||
serialize_u32(levy_identifier_length) \
|
SERIALIZE_TAGGED((const uint8_t *) levy_namespace, levy_namespace_length);
|
||||||
serialize_write((uint8_t *) levy_namespace, levy_namespace_length) \
|
SERIALIZE_TAGGED((const uint8_t *) levy_mosaic, levy_mosaic_length);
|
||||||
serialize_write((uint8_t *) levy_mosaic, levy_mosaic_length) \
|
SERIALIZE_U64(levy_fee);
|
||||||
serialize_u64(levy_fee)
|
|
||||||
|
|
||||||
#include "nem_serialize.h"
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
SERIALIZE_U32(0);
|
||||||
#define NEM_SERIALIZE \
|
|
||||||
serialize_u32(0)
|
|
||||||
|
|
||||||
#include "nem_serialize.h"
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rewrite length
|
// Rewrite length
|
||||||
nem_write_u32(&state, ctx->offset - state.offset - sizeof(uint32_t));
|
nem_write_u32(&state, ctx->offset - state.offset - sizeof(uint32_t));
|
||||||
|
|
||||||
#define NEM_SERIALIZE \
|
SERIALIZE_TAGGED((const uint8_t *) creation_sink, NEM_ADDRESS_SIZE);
|
||||||
serialize_write((uint8_t *) creation_sink, NEM_ADDRESS_SIZE) \
|
SERIALIZE_U64(creation_fee);
|
||||||
serialize_u64(creation_fee)
|
|
||||||
|
|
||||||
#include "nem_serialize.h"
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -517,14 +484,11 @@ bool nem_transaction_create_mosaic_supply_change(nem_transaction_ctx *ctx,
|
|||||||
size_t mosaic_length = strlen(mosaic);
|
size_t mosaic_length = strlen(mosaic);
|
||||||
size_t identifier_length = sizeof(uint32_t) + namespace_length + sizeof(uint32_t) + mosaic_length;
|
size_t identifier_length = sizeof(uint32_t) + namespace_length + sizeof(uint32_t) + mosaic_length;
|
||||||
|
|
||||||
#define NEM_SERIALIZE \
|
SERIALIZE_U32(identifier_length);
|
||||||
serialize_u32(identifier_length) \
|
SERIALIZE_TAGGED((const uint8_t *) namespace, namespace_length);
|
||||||
serialize_write((uint8_t *) namespace, namespace_length) \
|
SERIALIZE_TAGGED((const uint8_t *) mosaic, mosaic_length);
|
||||||
serialize_write((uint8_t *) mosaic, mosaic_length) \
|
SERIALIZE_U32(type);
|
||||||
serialize_u32(type) \
|
SERIALIZE_U64(delta);
|
||||||
serialize_u64(delta)
|
|
||||||
|
|
||||||
#include "nem_serialize.h"
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -551,10 +515,7 @@ bool nem_transaction_create_aggregate_modification(nem_transaction_ctx *ctx,
|
|||||||
deadline);
|
deadline);
|
||||||
if (!ret) return false;
|
if (!ret) return false;
|
||||||
|
|
||||||
#define NEM_SERIALIZE \
|
SERIALIZE_U32(modifications);
|
||||||
serialize_u32(modifications)
|
|
||||||
|
|
||||||
#include "nem_serialize.h"
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -563,12 +524,9 @@ bool nem_transaction_write_cosignatory_modification(nem_transaction_ctx *ctx,
|
|||||||
uint32_t type,
|
uint32_t type,
|
||||||
const ed25519_public_key cosignatory) {
|
const ed25519_public_key cosignatory) {
|
||||||
|
|
||||||
#define NEM_SERIALIZE \
|
SERIALIZE_U32(sizeof(uint32_t) + sizeof(uint32_t) + sizeof(ed25519_public_key));
|
||||||
serialize_u32(sizeof(uint32_t) + sizeof(uint32_t) + sizeof(ed25519_public_key)) \
|
SERIALIZE_U32(type);
|
||||||
serialize_u32(type) \
|
SERIALIZE_TAGGED(cosignatory, sizeof(ed25519_public_key));
|
||||||
serialize_write(cosignatory, sizeof(ed25519_public_key))
|
|
||||||
|
|
||||||
#include "nem_serialize.h"
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -576,11 +534,8 @@ bool nem_transaction_write_cosignatory_modification(nem_transaction_ctx *ctx,
|
|||||||
bool nem_transaction_write_minimum_cosignatories(nem_transaction_ctx *ctx,
|
bool nem_transaction_write_minimum_cosignatories(nem_transaction_ctx *ctx,
|
||||||
int32_t relative_change) {
|
int32_t relative_change) {
|
||||||
|
|
||||||
#define NEM_SERIALIZE \
|
SERIALIZE_U32(sizeof(uint32_t));
|
||||||
serialize_u32(sizeof(uint32_t)) \
|
SERIALIZE_U32((uint32_t) relative_change);
|
||||||
serialize_u32((uint32_t) relative_change)
|
|
||||||
|
|
||||||
#include "nem_serialize.h"
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -607,11 +562,8 @@ bool nem_transaction_create_importance_transfer(nem_transaction_ctx *ctx,
|
|||||||
deadline);
|
deadline);
|
||||||
if (!ret) return false;
|
if (!ret) return false;
|
||||||
|
|
||||||
#define NEM_SERIALIZE \
|
SERIALIZE_U32(mode);
|
||||||
serialize_u32(mode) \
|
SERIALIZE_TAGGED(remote, sizeof(ed25519_public_key));
|
||||||
serialize_write(remote, sizeof(ed25519_public_key))
|
|
||||||
|
|
||||||
#include "nem_serialize.h"
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
#define serialize_u32(data) + sizeof(uint32_t)
|
|
||||||
#define serialize_u64(data) + sizeof(uint64_t)
|
|
||||||
#define serialize_write(data, length) + (length)
|
|
||||||
|
|
||||||
if (!nem_can_write(ctx, NEM_SERIALIZE)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef serialize_u32
|
|
||||||
#undef serialize_u64
|
|
||||||
#undef serialize_write
|
|
||||||
|
|
||||||
#define serialize_u32(data) nem_write_u32(ctx, (data));
|
|
||||||
#define serialize_u64(data) nem_write_u64(ctx, (data));
|
|
||||||
#define serialize_write(data, length) nem_write(ctx, (data), (length));
|
|
||||||
|
|
||||||
NEM_SERIALIZE
|
|
||||||
|
|
||||||
#undef serialize_u32
|
|
||||||
#undef serialize_u64
|
|
||||||
#undef serialize_write
|
|
||||||
|
|
||||||
#undef NEM_SERIALIZE
|
|
Loading…
Reference in New Issue
Block a user