Commit b19772f1 authored by xpetrak2's avatar xpetrak2
Browse files

Definition of trade operations

Path to trade directories and their creation
Definition of generic trade operations
Definition of overriden trade operations for the trading type 'basic'
Declaration of trade parsing functions
parent 8bf438d0
......@@ -14,7 +14,7 @@ src_coincerd_SOURCES = \
src/json_parser.c src/json_parser.h \
src/linkedlist.c src/linkedlist.h \
src/log.c src/log.h \
src/market.h \
src/market.c src/market.h \
src/neighbours.c src/neighbours.h \
src/p2p.c src/p2p.h \
src/paths.c src/paths.h \
......
......@@ -71,7 +71,9 @@ static int create_dir(const char *dir_path, mode_t mode)
int create_dirs(const filepaths_t *paths)
{
if (create_dir(paths->config_dir, S_IRWXU) ||
create_dir(paths->data_dir, S_IRWXU)) {
create_dir(paths->data_dir, S_IRWXU) ||
create_dir(paths->trades_dir, S_IRWXU) ||
create_dir(paths->trades_basic_dir, S_IRWXU)) {
log_error("Creating directories");
return 1;
}
......
......@@ -69,13 +69,12 @@ int global_state_init(global_state_t *global_state)
}
linkedlist_init(&global_state->identities);
if (!(global_state->true_identity = identity_generate(0x00))) {
if (!(global_state->true_identity = identity_generate(
&global_state->identities,
0x00))) {
log_error("Creating our true identity");
return 1;
}
linkedlist_append(&global_state->identities,
global_state->true_identity);
linkedlist_init(&global_state->events);
linkedlist_init(&global_state->hosts);
linkedlist_init(&global_state->message_traces);
......
......@@ -23,7 +23,8 @@
#include "daemon_messages.h"
#include "json_parser.h"
#include "log.h"
#include "trade.h"
#include "trade_basic.h"
/* TODO: Implement */
/**
......@@ -179,6 +180,22 @@ int decode_message_data(const char *json_data,
return 1;
}
/* TODO: Implement */
/**
* Decode a JSON trade.
*
* @param json_trade Encoded JSON trade.
* @param trade Internal trade representation, dynamically
* allocated in here.
*
* @return 0 Successfully decoded.
* @return 1 Failure.
*/
int decode_trade(const char *json_trade, trade_t **trade)
{
return 0;
}
/* TODO: Implement */
/**
* Encode a daemon message into JSON format output.
......@@ -242,3 +259,18 @@ int encode_message_body(const message_body_t *body, char **json_body)
{
return 0;
}
/* TODO: Implement */
/**
* Encode a trade into JSON.
*
* @param trade Trade to encode.
* @param json_trade Encoded JSON trade.
*
* @return 0 Successfully encoded.
* @return 1 Failure.
*/
int encode_trade(const trade_t *trade, char **json_trade)
{
return 0;
}
......@@ -44,7 +44,11 @@ int decode_message_data(const char *json_data,
const enum message_type type,
void **data);
int decode_trade(const char *json_trade, trade_t **trade);
int encode_message(const message_t *message, char **json_message);
int encode_message_body(const message_body_t *body, char **json_body);
int encode_trade(const trade_t *trade, char **json_trade);
#endif /* JSON_PARSER_H */
/*
* Coincer
* Copyright (C) 2017-2018 Coincer Developers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "market.h"
void order_flags_set(order_t *order, int flags)
{
order->flags |= flags;
}
void order_flags_unset(order_t *order, int flags)
{
order->flags &= ~flags;
}
......@@ -25,7 +25,7 @@
/** Order that does not belong to us. */
#define ORDER_FOREIGN 0x01
/** Order that is being traded */
/** Order that is being traded. */
#define ORDER_TRADING 0x02
typedef struct s_order {
......@@ -39,4 +39,7 @@ typedef struct s_order {
linkedlist_node_t *node;
} order_t;
void order_flags_set(order_t *order, int flags);
void order_flags_unset(order_t *order, int flags);
#endif /* MARKET_H */
......@@ -24,6 +24,9 @@
#include "log.h"
#include "paths.h"
#define TRADES_DIR_NAME "trades"
#define TRADES_BASIC_DIR_NAME "basic"
#define HOSTS_FILE_NAME "hosts"
static int set_dir_path(const char *location,
......@@ -166,7 +169,13 @@ static int set_dir_path(const char *location,
int setup_paths(filepaths_t *filepaths)
{
if (set_config_dir_path(&filepaths->config_dir) ||
set_data_dir_path(&filepaths->data_dir)) {
set_data_dir_path(&filepaths->data_dir) ||
set_dir_path(filepaths->data_dir,
TRADES_DIR_NAME,
&filepaths->trades_dir) ||
set_dir_path(filepaths->trades_dir,
TRADES_BASIC_DIR_NAME,
&filepaths->trades_basic_dir)) {
log_error("Setting directory paths failed");
return 1;
}
......@@ -187,6 +196,8 @@ void clear_paths(filepaths_t *filepaths)
{
free(filepaths->config_dir);
free(filepaths->data_dir);
free(filepaths->trades_dir);
free(filepaths->trades_basic_dir);
free(filepaths->hosts);
}
......@@ -23,6 +23,9 @@
typedef struct s_filepaths {
char *config_dir; /**< Config directory. */
char *data_dir; /**< Data directory. */
char *trades_dir; /**< Directory with trades. */
/** Trades' subdirectory with trades of type 'basic'. */
char *trades_basic_dir;
/**< Path to file with addresses of hosts. */
char *hosts;
......
......@@ -97,14 +97,16 @@ void identity_flags_unset(identity_t *identity, int flags)
}
/**
* Generate an identity, including its initial nonce value.
* Generate an identity, including its initial nonce value and append it to the
* list of our identities.
*
* @param identities List of our identities.
* @param flags The flags of the identity.
*
* @return identity_t Dynamically allocated identity.
* @return NULL Allocation failure.
*/
identity_t *identity_generate(int flags)
identity_t *identity_generate(linkedlist_t *identities, int flags)
{
identity_t *identity;
......@@ -113,6 +115,11 @@ identity_t *identity_generate(int flags)
log_error("Creating a new identity");
return NULL;
}
if (!(identity->node = linkedlist_append(identities, identity))) {
free(identity);
log_error("Storing a new identity");
return NULL;
}
generate_keypair(&identity->keypair);
identity->nonce_value = get_random_uint64_t();
......
......@@ -62,6 +62,8 @@ typedef struct s_identity {
time_t last_adv;
/** The last used nonce with this identity. */
uint64_t nonce_value;
/** The identity's node in the list of identities. */
linkedlist_node_t *node;
} identity_t;
int identifier_empty(const unsigned char id[PUBLIC_KEY_SIZE]);
......@@ -70,7 +72,7 @@ identity_t *identity_find(const linkedlist_t *identities,
const unsigned char *identifier);
void identity_flags_set(identity_t *identity, int flags);
void identity_flags_unset(identity_t *identity, int flags);
identity_t *identity_generate(int flags);
identity_t *identity_generate(linkedlist_t *identities, int flags);
int nonce_is_stale(const nonce_t *nonce, const time_t current_time);
int nonce_store(linkedlist_t *nonces, uint64_t value);
......
......@@ -619,9 +619,8 @@ void routing_loop_remove(linkedlist_t *routing_table,
next_hop = route_next_hop_get(route);
if (!next_hop) {
/* create a temporary identity for the p2p.route.sol */
identity = identity_generate(IDENTITY_TMP);
/* if appending succeeded */
if (linkedlist_append(identities, identity)) {
if ((identity = identity_generate(identities,
IDENTITY_TMP))) {
/* if successfully sent */
if (!send_p2p_route_sol(neighbours,
identity,
......@@ -629,7 +628,6 @@ void routing_loop_remove(linkedlist_t *routing_table,
return;
}
}
free(identity);
route_delete(routing_table, dest_id);
}
}
......
......@@ -20,14 +20,194 @@
#include <string.h>
#include "crypto.h"
#include "global_state.h"
#include "linkedlist.h"
#include "log.h"
#include "market.h"
#include "paths.h"
#include "peers.h"
#include "trade.h"
#include "trade_basic.h"
/**
* Delete trade.execution message.
* Cancel a trade.
*
* @param trade_execution The message.
* @param type Trading type of the trade.execution.
* @param trade Trade to be cancelled.
*/
void trade_cancel(trade_t *trade)
{
switch (trade->type) {
case TT_BASIC:
trade_basic_cancel(trade);
break;
}
order_flags_unset(trade->order, ORDER_TRADING);
linkedlist_delete_safely(trade->node, trade_clear);
}
/**
* Clear trade's data.
*
* @param trade Trade to be cleared.
*/
void trade_clear(trade_t *trade)
{
switch (trade->type) {
case TT_BASIC:
trade_basic_clear(trade->data);
break;
}
if (trade->my_identity) {
linkedlist_delete(trade->my_identity->node);
}
}
/**
* Compare our trading identity to other identity.
*
* @param trade Trade with our trading identity.
* @param identity Compare to this identity.
*
* @return 0 The identities match.
* @return 1 The identities are different.
*/
int trade_cmp_identity(const trade_t *trade, const identity_t *identity)
{
return trade->my_identity != identity;
}
/**
* Compare order ID of a trade to other order ID.
*
* @param trade Order ID of this trade.
* @param order_id Compare to this order ID.
*
* @return 0 The IDs match.
* @return 1 The IDs are different.
*/
int trade_cmp_order_id(const trade_t *trade, const unsigned char *order_id)
{
return memcmp(trade->order->id, order_id, SHA3_256_SIZE);
}
/**
* Create and store a new trade including a newly generated identity.
*
* @param trades List of our trades.
* @param identities List of our identities.
* @param order Trade related to this order.
* @param cp_id Counterparty's identifier.
* @param type Type of the trade.
*
* @return trade_t Trade successfully created.
* @return NULL Failure.
*/
trade_t *trade_create(linkedlist_t *trades,
linkedlist_t *identities,
order_t *order,
const unsigned char *cp_id,
enum trade_type type)
{
trade_t *trade;
trade = (trade_t *) malloc(sizeof(trade_t));
if (!trade) {
log_error("Creating a trade");
return NULL;
}
if (!(trade->node = linkedlist_append(trades, trade))) {
free(trade);
log_error("Storing a new trade");
return NULL;
}
if (!(trade->my_identity = identity_generate(identities, 0x0))) {
linkedlist_delete(trade->node);
log_error("Creating trade-specific identity");
return NULL;
}
switch (type) {
case TT_BASIC:
if (!(trade->data = malloc(sizeof(trade_basic_t)))) {
linkedlist_delete_safely(trade->node,
trade_clear);
log_error("Creating trade data");
return NULL;
}
trade_basic_init_data(trade->data);
break;
}
trade->order = order;
trade->type = type;
trade->step = TS_PROPOSAL;
memset(&trade->my_keypair, 0x0, sizeof(keypair_t));
memcpy(trade->cp_identifier, cp_id, PUBLIC_KEY_SIZE);
memset(trade->cp_pubkey, 0x0, PUBLIC_KEY_SIZE);
return trade;
}
/**
* Find a trade by one of its attributes.
*
* @param trades List of our trades.
* @param attribute Find by this attribute.
* @param cmp_func Comparing function. Returns 0 for a match.
*
* @return trade_t The trade we want.
* @return NULL Trade unknown.
*/
trade_t *trade_find(const linkedlist_t *trades,
const void *attribute,
int (*cmp_func) (const trade_t *trade,
const void *attribute))
{
const linkedlist_node_t *node;
trade_t *trade;
node = linkedlist_get_first(trades);
while (node) {
trade = (trade_t *) node->data;
if (!cmp_func(trade, attribute)) {
return trade;
}
node = linkedlist_get_next(trades, node);
}
return NULL;
}
/**
* Update trade's data with the next trading step.
*
* @param trade Trade to be updated.
* @param next_step Next step of a trade.
* @param data Next step's data.
*
* @return 0 Successfully updated.
* @return 1 Incorrect data.
*/
int trade_update(trade_t *trade, enum trade_step next_step, const void *data)
{
switch (trade->type) {
case TT_BASIC:
return trade_basic_update(trade, next_step, data);
}
return 1;
}
/**
* Delete trade.execution payload.
*
* @param trade_execution The payload to be deleted.
* @param type Type of execution's trade.
* @param step trade.execution's step.
*/
void trade_execution_delete(trade_execution_t *trade_execution,
......@@ -61,3 +241,49 @@ void trade_proposal_init(trade_proposal_t *trade_proposal, const trade_t *trade)
trade_proposal_basic_init(trade_proposal, trade->data);
}
}
/**
* Get the next step of a trade.
*
* @param trade The next step of this trade.
*
* @return trade_step The next step.
*/
enum trade_step trade_step_get_next(const trade_t *trade)
{
switch (trade->type) {
case TT_BASIC:
return trade_step_basic_get_next(trade);
}
}
/**
* Perform the current step of a trade.
*
* @param trade Use this trade.
* @param global_state The global state.
*
* @return 0 Success.
* @return 1 Failure.
*/
int trade_step_perform(trade_t *trade, global_state_t *global_state)
{
switch (trade->type) {
case TT_BASIC:
return trade_step_basic_perform(trade, global_state);
}
}
/**
* Load saved trades into memory.
*
* @param trades Store loaded trades in here.
* @param paths Paths to trade directories.
*
* @return 0 Successfully loaded.
* @return 1 Failure.
*/
int trades_load(linkedlist_t *trades, filepaths_t *paths)
{
return trades_basic_load(trades, paths->trades_basic_dir);
}
......@@ -20,8 +20,10 @@
#define TRADE_H
#include "crypto.h"
#include "global_state.h"
#include "linkedlist.h"
#include "market.h"
#include "paths.h"
#include "peers.h"
/**
......@@ -43,8 +45,8 @@ enum trade_step {
TS_COINS_COMMITMENT, /**< Committing coins into a blackchain. */
/** Waiting for the counterparty to commit their coins. */
TS_COINS_CP_COMMITMENT,
TS_COINS_CLAIM, /** Coins claim. */
TS_DONE /** Trade successfully completed. */
TS_COINS_CLAIM, /**< Coins claim. */
TS_DONE /**< Trade successfully completed. */
};
/**
......@@ -94,6 +96,21 @@ typedef struct s_trade_reject {
unsigned char order[SHA3_256_SIZE]; /**< Order id. */
} trade_reject_t;
void trade_cancel(trade_t *trade);
void trade_clear(trade_t *trade);
int trade_cmp_identity(const trade_t *trade, const identity_t *identity);
int trade_cmp_order_id(const trade_t *trade, const unsigned char *order_id);
trade_t *trade_create(linkedlist_t *trades,
linkedlist_t *identities,
order_t *order,
const unsigned char *cp_id,
enum trade_type type);
trade_t *trade_find(const linkedlist_t *trades,
const void *attribute,
int (*cmp_func) (const trade_t *trade,
const void *attribute));
int trade_update(trade_t *trade, enum trade_step next_step, const void *data);
void trade_execution_delete(trade_execution_t *data,
enum trade_type type,
enum trade_step step);
......@@ -101,4 +118,9 @@ void trade_execution_delete(trade_execution_t *data,
void trade_proposal_init(trade_proposal_t *trade_proposal,
const trade_t *trade);
enum trade_step trade_step_get_next(const trade_t *trade);
int trade_step_perform(trade_t *trade, global_state_t *global_state);
int trades_load(linkedlist_t *trades, filepaths_t *paths);
#endif /* TRADE_H */
......@@ -16,15 +16,262 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _POSIX_SOURCE /* fileno */
#include <dirent.h>
#include <sodium.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "crypto.h"
#include "global_state.h"
#include "json_parser.h"
#include "log.h"
#include "trade.h"
#include "trade_basic.h"
#define COMMITTED_HEX_LEN 2 * TRADE_BASIC_COMMITTED_SIZE
#define ORDER_ID_HEX_LEN 2 * SHA3_256_SIZE
static int trade_script_generate(trade_t *trade, global_state_t *global_state);
static int trade_script_originator(const trade_t *trade);
static int trade_script_validate(const trade_t *trade, const char *script);
/**
* Cancel a trade.
*
* @param trade Trade to be cancelled.
*/
void trade_basic_cancel(trade_t *trade)
{
trade_basic_t *trade_data;
trade_data = (trade_basic_t *) trade->data;
/* if we're still in the phase 0 */
if (!trade_data->my_script || !trade_data->cp_script) {
linkedlist_delete_safely(trade->node, trade_clear);
return;
}
/* TODO: refund/claim coins here */
}
/**
* Clear data of a trade.
*
* @param data Data of the trade.
*/
void trade_basic_clear(trade_basic_t *data)
{
if (data->my_script) {
free(data->my_script);
}
if (data->cp_script) {
free(data->cp_script);
}
}
/**
* Initialize data of a basic trade.
*
* @param data The trade data.
*/
void trade_basic_init_data(trade_basic_t *data)
{
memset(data->x, 0x0, TRADE_BASIC_X_SIZE);
memset(data->hx, 0x0, RIPEMD_160_SIZE);
memset(data->my_commitment, 0x0, SHA3_256_SIZE);
memset(data->my_committed, 0x0, TRADE_BASIC_COMMITTED_SIZE);