Skip to content
This repository was archived by the owner on Apr 24, 2022. It is now read-only.

Commit 3f72ae8

Browse files
author
Gav Wood
committedMay 5, 2015
Merge pull request #41 from LefterisJP/finalize_and_use_new_api
Finalize and use new api
2 parents bed7c62 + b90dd99 commit 3f72ae8

9 files changed

+477
-428
lines changed
 

‎CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ set(FILES util.h
2020
data_sizes.h)
2121

2222
if (MSVC)
23-
list(APPEND FILES util.c io_win32.c mmap_win32.c)
23+
list(APPEND FILES util_win32.c io_win32.c mmap_win32.c)
2424
else()
2525
list(APPEND FILES io_posix.c)
2626
endif()

‎ethash.h

+34-187
Original file line numberDiff line numberDiff line change
@@ -37,35 +37,15 @@
3737
#define ETHASH_DATASET_PARENTS 256
3838
#define ETHASH_CACHE_ROUNDS 3
3939
#define ETHASH_ACCESSES 64
40+
#define ETHASH_DAG_MAGIC_NUM_SIZE 8
41+
#define ETHASH_DAG_MAGIC_NUM 0xFEE1DEADBADDCAFE
4042

4143
#ifdef __cplusplus
4244
extern "C" {
4345
#endif
4446

45-
// LTODO: for consistency's sake maybe use ethash_params_t?
46-
typedef struct ethash_params {
47-
/// Size of full data set (in bytes, multiple of mix size (128)).
48-
uint64_t full_size;
49-
/// Size of compute cache (in bytes, multiple of node size (64)).
50-
uint64_t cache_size;
51-
} ethash_params;
52-
5347
/// Type of a seedhash/blockhash e.t.c.
5448
typedef struct ethash_h256 { uint8_t b[32]; } ethash_h256_t;
55-
static inline uint8_t ethash_h256_get(ethash_h256_t const* hash, unsigned int i)
56-
{
57-
return hash->b[i];
58-
}
59-
60-
static inline void ethash_h256_set(ethash_h256_t* hash, unsigned int i, uint8_t v)
61-
{
62-
hash->b[i] = v;
63-
}
64-
65-
static inline void ethash_h256_reset(ethash_h256_t* hash)
66-
{
67-
memset(hash, 0, 32);
68-
}
6949

7050
// convenience macro to statically initialize an h256_t
7151
// usage:
@@ -81,55 +61,20 @@ struct ethash_full;
8161
typedef struct ethash_full* ethash_full_t;
8262
typedef int(*ethash_callback_t)(unsigned);
8363

84-
// LTODO: for consistency's sake maybe use ethash_return_value_t?
8564
typedef struct ethash_return_value {
8665
ethash_h256_t result;
8766
ethash_h256_t mix_hash;
88-
} ethash_return_value;
89-
90-
uint64_t ethash_get_datasize(uint32_t const block_number);
91-
uint64_t ethash_get_cachesize(uint32_t const block_number);
92-
93-
// initialize the parameters
94-
static inline void ethash_params_init(ethash_params* params, uint32_t const block_number)
95-
{
96-
params->full_size = ethash_get_datasize(block_number);
97-
params->cache_size = ethash_get_cachesize(block_number);
98-
}
99-
100-
// LTODO: for consistency's sake maybe use ethash_cache_t?
101-
typedef struct ethash_cache {
102-
void* mem;
103-
} ethash_cache;
104-
105-
/**
106-
* Allocate and initialize a new ethash_cache object
107-
*
108-
* @param params The parameters to initialize it with. We are interested in
109-
* the cache_size from here
110-
* @param seed Block seedhash to be used during the computation of the
111-
* cache nodes
112-
* @return Newly allocated ethash_cache on success or NULL in case of
113-
* ERRNOMEM or invalid parameters used for @ref ethash_compute_cache_nodes()
114-
*/
115-
ethash_cache* ethash_cache_new(ethash_params const* params, ethash_h256_t const* seed);
116-
/**
117-
* Frees a previously allocated ethash_cache
118-
* @param c The object to free
119-
*/
120-
void ethash_cache_delete(ethash_cache* c);
67+
bool success;
68+
} ethash_return_value_t;
12169

12270
/**
12371
* Allocate and initialize a new ethash_light handler
12472
*
125-
* @param params The parameters to initialize it with. We are interested in
126-
* the cache_size from here
127-
* @param seed Block seedhash to be used during the computation of the
128-
* cache nodes
129-
* @return Newly allocated ethash_light handler or NULL in case of
130-
* ERRNOMEM or invalid parameters used for @ref ethash_compute_cache_nodes()
73+
* @param block_number The block number for which to create the handler
74+
* @return Newly allocated ethash_light handler or NULL in case of
75+
* ERRNOMEM or invalid parameters used for @ref ethash_compute_cache_nodes()
13176
*/
132-
ethash_light_t ethash_light_new(ethash_params const* params, ethash_h256_t const* seed);
77+
ethash_light_t ethash_light_new(uint64_t block_number);
13378
/**
13479
* Frees a previously allocated ethash_light handler
13580
* @param light The light handler to free
@@ -138,63 +83,33 @@ void ethash_light_delete(ethash_light_t light);
13883
/**
13984
* Calculate the light client data
14085
*
141-
* @param ret An object of ethash_return_value to hold the return value
14286
* @param light The light client handler
143-
* @param params The parameters to use
14487
* @param header_hash The header hash to pack into the mix
14588
* @param nonce The nonce to pack into the mix
146-
* @return true if all went well and false if there were invalid
147-
* parameters given.
89+
* @return an object of ethash_return_value_t holding the return values
14890
*/
149-
bool ethash_light_compute(
150-
ethash_return_value* ret,
91+
ethash_return_value_t ethash_light_compute(
15192
ethash_light_t light,
152-
ethash_params const* params,
153-
const ethash_h256_t* header_hash,
154-
uint64_t const nonce
93+
ethash_h256_t const header_hash,
94+
uint64_t nonce
15595
);
156-
/**
157-
* Get a pointer to the cache object held by the light client
158-
*
159-
* @param light The light client whose cache to request
160-
* @return A pointer to the cache held by the light client or NULL if
161-
* there was no cache in the first place
162-
*/
163-
ethash_cache* ethash_light_get_cache(ethash_light_t light);
164-
/**
165-
* Move the memory ownership of the cache somewhere else
166-
*
167-
* @param light The light client whose cache's memory ownership to acquire.
168-
* After this function concludes it will no longer have a cache.
169-
* @return A pointer to the moved cache or NULL if there was no cache in the first place
170-
*/
171-
ethash_cache* ethash_light_acquire_cache(ethash_light_t light);
17296

17397
/**
17498
* Allocate and initialize a new ethash_full handler
17599
*
176-
* @param dirname The directory in which to put the DAG file.
177-
* @param seedhash The seed hash of the block. Used in the DAG file naming.
178-
* @param params The parameters to initialize it with. We are interested in
179-
* the full_size from here
180-
* @param cache A cache object to use that was allocated with @ref ethash_cache_new().
181-
* Iff this function succeeds the ethash_full_t will take memory
182-
* ownership of the cache and free it at deletion. If not then the user
183-
* still has to handle freeing of the cache himself.
184-
* @param callback A callback function with signature of @ref ethash_callback_t
185-
* It accepts an unsigned with which a progress of DAG calculation
186-
* can be displayed. If all goes well the callback should return 0.
187-
* If a non-zero value is returned then DAG generation will stop.
188-
* @return Newly allocated ethash_full handler or NULL in case of
189-
* ERRNOMEM or invalid parameters used for @ref ethash_compute_full_data()
100+
* @param light The light handler containing the cache.
101+
* @param callback A callback function with signature of @ref ethash_callback_t
102+
* It accepts an unsigned with which a progress of DAG calculation
103+
* can be displayed. If all goes well the callback should return 0.
104+
* If a non-zero value is returned then DAG generation will stop.
105+
* Be advised. A progress value of 100 means that DAG creation is
106+
* almost complete and that this function will soon return succesfully.
107+
* It does not mean that the function has already had a succesfull return.
108+
* @return Newly allocated ethash_full handler or NULL in case of
109+
* ERRNOMEM or invalid parameters used for @ref ethash_compute_full_data()
190110
*/
191-
ethash_full_t ethash_full_new(
192-
char const* dirname,
193-
ethash_h256_t const* seed_hash,
194-
ethash_params const* params,
195-
ethash_cache const* cache,
196-
ethash_callback_t callback
197-
);
111+
ethash_full_t ethash_full_new(ethash_light_t light, ethash_callback_t callback);
112+
198113
/**
199114
* Frees a previously allocated ethash_full handler
200115
* @param full The light handler to free
@@ -203,97 +118,29 @@ void ethash_full_delete(ethash_full_t full);
203118
/**
204119
* Calculate the full client data
205120
*
206-
* @param ret An object of ethash_return_value to hold the return value
207121
* @param full The full client handler
208-
* @param params The parameters to use
209122
* @param header_hash The header hash to pack into the mix
210123
* @param nonce The nonce to pack into the mix
211-
* @return true if all went well and false if there were invalid
212-
* parameters given or if there was a callback given and
213-
* at some point return a non-zero value
124+
* @return An object of ethash_return_value to hold the return value
214125
*/
215-
bool ethash_full_compute(
216-
ethash_return_value* ret,
126+
ethash_return_value_t ethash_full_compute(
217127
ethash_full_t full,
218-
ethash_params const* params,
219-
ethash_h256_t const* header_hash,
220-
uint64_t const nonce
128+
ethash_h256_t const header_hash,
129+
uint64_t nonce
221130
);
222131
/**
223-
* Get a pointer to the cache object held by the full client
224-
*
225-
* @param full The full client whose cache to request
226-
* @return A pointer to the cache held by the full client or NULL
227-
* if there was no cache in the first place
132+
* Get a pointer to the full DAG data
228133
*/
229-
ethash_cache* ethash_full_get_cache(ethash_full_t full);
134+
void const* ethash_full_dag(ethash_full_t full);
230135
/**
231-
* Move the memory ownership of the cache somewhere else
232-
*
233-
* @param full The full client whose cache's memory ownership to acquire.
234-
* After this function concludes it will no longer have a cache.
235-
* @return A pointer to the moved cache or NULL if there was no cache in the first place
136+
* Get the size of the DAG data
236137
*/
237-
ethash_cache* ethash_full_acquire_cache(ethash_full_t full);
238-
239-
void ethash_get_seedhash(ethash_h256_t *seedhash, const uint32_t block_number);
240-
241-
// Returns if hash is less than or equal to difficulty
242-
static inline int ethash_check_difficulty(
243-
ethash_h256_t const* hash,
244-
ethash_h256_t const* difficulty
245-
)
246-
{
247-
// Difficulty is big endian
248-
for (int i = 0; i < 32; i++) {
249-
if (ethash_h256_get(hash, i) == ethash_h256_get(difficulty, i)) {
250-
continue;
251-
}
252-
return ethash_h256_get(hash, i) < ethash_h256_get(difficulty, i);
253-
}
254-
return 1;
255-
}
256-
257-
int ethash_quick_check_difficulty(
258-
ethash_h256_t const* header_hash,
259-
uint64_t const nonce,
260-
ethash_h256_t const* mix_hash,
261-
ethash_h256_t const* difficulty
262-
);
263-
138+
uint64_t ethash_full_dag_size(ethash_full_t full);
264139

265140
/**
266-
* =========================
267-
* = DEPRECATED API =
268-
* =========================
269-
*
270-
* Kept for backwards compatibility with whoever still uses it. Please consider
271-
* switching to the new API (look above)
272-
*/
273-
void ethash_mkcache(ethash_cache* cache, ethash_params const* params, ethash_h256_t const* seed);
274-
void ethash_full(
275-
ethash_return_value* ret,
276-
void const* full_mem,
277-
ethash_params const* params,
278-
ethash_h256_t const* header_hash,
279-
uint64_t const nonce
280-
);
281-
void ethash_light(
282-
ethash_return_value* ret,
283-
ethash_cache const* cache,
284-
ethash_params const* params,
285-
ethash_h256_t const* header_hash,
286-
uint64_t const nonce
287-
);
288-
/**
289-
* Compute the memory data for a full node's memory
290-
*
291-
* @param mem A pointer to an ethash full's memory
292-
* @param params The parameters to compute the data with
293-
* @param cache A cache object to use in the calculation
294-
* @return true if all went fine and false for invalid parameters
141+
* Calculate the seedhash for a given block number
295142
*/
296-
bool ethash_compute_full_data(void* mem, ethash_params const* params, ethash_cache const* cache);
143+
ethash_h256_t ethash_get_seedhash(uint64_t block_number);
297144

298145
#ifdef __cplusplus
299146
}

‎internal.c

+165-182
Large diffs are not rendered by default.

‎internal.h

+115-7
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,112 @@ typedef union node {
3131

3232
} node;
3333

34+
static inline uint8_t ethash_h256_get(ethash_h256_t const* hash, unsigned int i)
35+
{
36+
return hash->b[i];
37+
}
38+
39+
static inline void ethash_h256_set(ethash_h256_t* hash, unsigned int i, uint8_t v)
40+
{
41+
hash->b[i] = v;
42+
}
43+
44+
static inline void ethash_h256_reset(ethash_h256_t* hash)
45+
{
46+
memset(hash, 0, 32);
47+
}
48+
49+
// Returns if hash is less than or equal to difficulty
50+
static inline int ethash_check_difficulty(
51+
ethash_h256_t const* hash,
52+
ethash_h256_t const* difficulty
53+
)
54+
{
55+
// Difficulty is big endian
56+
for (int i = 0; i < 32; i++) {
57+
if (ethash_h256_get(hash, i) == ethash_h256_get(difficulty, i)) {
58+
continue;
59+
}
60+
return ethash_h256_get(hash, i) < ethash_h256_get(difficulty, i);
61+
}
62+
return 1;
63+
}
64+
65+
int ethash_quick_check_difficulty(
66+
ethash_h256_t const* header_hash,
67+
uint64_t const nonce,
68+
ethash_h256_t const* mix_hash,
69+
ethash_h256_t const* difficulty
70+
);
71+
3472
struct ethash_light {
35-
ethash_cache* cache;
73+
void* cache;
74+
uint64_t cache_size;
75+
uint64_t block_number;
3676
};
3777

78+
/**
79+
* Allocate and initialize a new ethash_light handler. Internal version
80+
*
81+
* @param cache_size The size of the cache in bytes
82+
* @param seed Block seedhash to be used during the computation of the
83+
* cache nodes
84+
* @return Newly allocated ethash_light handler or NULL in case of
85+
* ERRNOMEM or invalid parameters used for @ref ethash_compute_cache_nodes()
86+
*/
87+
ethash_light_t ethash_light_new_internal(uint64_t cache_size, ethash_h256_t const* seed);
88+
89+
/**
90+
* Calculate the light client data. Internal version.
91+
*
92+
* @param light The light client handler
93+
* @param full_size The size of the full data in bytes.
94+
* @param header_hash The header hash to pack into the mix
95+
* @param nonce The nonce to pack into the mix
96+
* @return The resulting hash.
97+
*/
98+
ethash_return_value_t ethash_light_compute_internal(
99+
ethash_light_t light,
100+
uint64_t full_size,
101+
ethash_h256_t const header_hash,
102+
uint64_t nonce
103+
);
104+
38105
struct ethash_full {
39106
FILE* file;
40-
size_t file_size;
41-
ethash_cache* cache;
107+
uint64_t file_size;
42108
node* data;
43-
ethash_callback_t callback;
44109
};
45110

111+
/**
112+
* Allocate and initialize a new ethash_full handler. Internal version.
113+
*
114+
* @param dirname The directory in which to put the DAG file.
115+
* @param seedhash The seed hash of the block. Used in the DAG file naming.
116+
* @param full_size The size of the full data in bytes.
117+
* @param cache A cache object to use that was allocated with @ref ethash_cache_new().
118+
* Iff this function succeeds the ethash_full_t will take memory
119+
* memory ownership of the cache and free it at deletion. If
120+
* not then the user still has to handle freeing of the cache himself.
121+
* @param callback A callback function with signature of @ref ethash_callback_t
122+
* It accepts an unsigned with which a progress of DAG calculation
123+
* can be displayed. If all goes well the callback should return 0.
124+
* If a non-zero value is returned then DAG generation will stop.
125+
* @return Newly allocated ethash_full handler or NULL in case of
126+
* ERRNOMEM or invalid parameters used for @ref ethash_compute_full_data()
127+
*/
128+
ethash_full_t ethash_full_new_internal(
129+
char const* dirname,
130+
ethash_h256_t const seed_hash,
131+
uint64_t full_size,
132+
ethash_light_t const light,
133+
ethash_callback_t callback
134+
);
135+
46136
void ethash_calculate_dag_item(
47137
node* const ret,
48-
const unsigned node_index,
49-
ethash_params const* params,
50-
ethash_cache const* cache
138+
uint32_t node_index,
139+
ethash_light_t const cache
51140
);
52141

53142
void ethash_quick_hash(
@@ -57,6 +146,25 @@ void ethash_quick_hash(
57146
ethash_h256_t const* mix_hash
58147
);
59148

149+
uint64_t ethash_get_datasize(uint64_t const block_number);
150+
uint64_t ethash_get_cachesize(uint64_t const block_number);
151+
152+
/**
153+
* Compute the memory data for a full node's memory
154+
*
155+
* @param mem A pointer to an ethash full's memory
156+
* @param full_size The size of the full data in bytes
157+
* @param cache A cache object to use in the calculation
158+
* @param callback The callback function. Check @ref ethash_full_new() for details.
159+
* @return true if all went fine and false for invalid parameters
160+
*/
161+
bool ethash_compute_full_data(
162+
void* mem,
163+
uint64_t full_size,
164+
ethash_light_t const light,
165+
ethash_callback_t callback
166+
);
167+
60168
#ifdef __cplusplus
61169
}
62170
#endif

‎io.c

+47-28
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ enum ethash_io_rc ethash_io_prepare(
2626
char const* dirname,
2727
ethash_h256_t const seedhash,
2828
FILE** output_file,
29-
size_t file_size
29+
uint64_t file_size,
30+
bool force_create
3031
)
3132
{
3233
char mutable_name[DAG_MUTABLE_NAME_MAX_SIZE];
@@ -43,35 +44,53 @@ enum ethash_io_rc ethash_io_prepare(
4344
goto end;
4445
}
4546

46-
// try to open the file
47-
FILE* f = ethash_fopen(tmpfile, "rb+");
48-
if (f) {
49-
size_t found_size;
50-
if (!ethash_file_size(f, &found_size)) {
51-
fclose(f);
52-
goto free_memo;
47+
FILE *f;
48+
if (!force_create) {
49+
// try to open the file
50+
f = ethash_fopen(tmpfile, "rb+");
51+
if (f) {
52+
size_t found_size;
53+
if (!ethash_file_size(f, &found_size)) {
54+
fclose(f);
55+
goto free_memo;
56+
}
57+
if (file_size != found_size - ETHASH_DAG_MAGIC_NUM_SIZE) {
58+
fclose(f);
59+
ret = ETHASH_IO_MEMO_SIZE_MISMATCH;
60+
goto free_memo;
61+
}
62+
// compare the magic number, no need to care about endianess since it's local
63+
uint64_t magic_num;
64+
if (fread(&magic_num, ETHASH_DAG_MAGIC_NUM_SIZE, 1, f) != 1) {
65+
// I/O error
66+
fclose(f);
67+
ret = ETHASH_IO_MEMO_SIZE_MISMATCH;
68+
goto free_memo;
69+
}
70+
if (magic_num != ETHASH_DAG_MAGIC_NUM) {
71+
fclose(f);
72+
ret = ETHASH_IO_MEMO_SIZE_MISMATCH;
73+
goto free_memo;
74+
}
75+
ret = ETHASH_IO_MEMO_MATCH;
76+
goto set_file;
5377
}
54-
if (file_size != found_size) {
55-
fclose(f);
56-
ret = ETHASH_IO_MEMO_SIZE_MISMATCH;
57-
goto free_memo;
58-
}
59-
} else {
60-
// file does not exist, will need to be created
61-
f = ethash_fopen(tmpfile, "wb+");
62-
if (!f) {
63-
goto free_memo;
64-
}
65-
// make sure it's of the proper size
66-
if (fseek(f, file_size - 1, SEEK_SET) != 0) {
67-
fclose(f);
68-
goto free_memo;
69-
}
70-
fputc('\n', f);
71-
fflush(f);
72-
ret = ETHASH_IO_MEMO_MISMATCH;
73-
goto set_file;
7478
}
79+
80+
// file does not exist, will need to be created
81+
f = ethash_fopen(tmpfile, "wb+");
82+
if (!f) {
83+
goto free_memo;
84+
}
85+
// make sure it's of the proper size
86+
if (fseek(f, (long int)(file_size + ETHASH_DAG_MAGIC_NUM_SIZE - 1), SEEK_SET) != 0) {
87+
fclose(f);
88+
goto free_memo;
89+
}
90+
fputc('\n', f);
91+
fflush(f);
92+
ret = ETHASH_IO_MEMO_MISMATCH;
93+
goto set_file;
7594

7695
ret = ETHASH_IO_MEMO_MATCH;
7796
set_file:

‎io.h

+33-23
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,16 @@ enum ethash_io_rc {
6969
* mode, while on the case of mismatch a new file is created
7070
* on write mode
7171
* @param[in] file_size The size that the DAG file should have on disk
72+
* @param[out] force_create If true then there is no check to see if the file
73+
* already exists
7274
* @return For possible return values @see enum ethash_io_rc
7375
*/
7476
enum ethash_io_rc ethash_io_prepare(
7577
char const* dirname,
7678
ethash_h256_t const seedhash,
7779
FILE** output_file,
78-
size_t file_size
80+
uint64_t file_size,
81+
bool force_create
7982
);
8083

8184
/**
@@ -112,7 +115,7 @@ char* ethash_strncat(char* dest, size_t dest_size, char const* src, size_t count
112115

113116
/**
114117
* A cross-platform mkdir wrapper to create a directory or assert it's there
115-
*
118+
*
116119
* @param dirname The full path of the directory to create
117120
* @return true if the directory was created or if it already
118121
* existed
@@ -130,12 +133,39 @@ bool ethash_file_size(FILE* f, size_t* ret_size);
130133

131134
/**
132135
* Get a file descriptor number from a FILE stream
133-
*
136+
*
134137
* @param f The file stream whose fd to get
135138
* @return Platform specific fd handler
136139
*/
137140
int ethash_fileno(FILE* f);
138141

142+
/**
143+
* Create the filename for the DAG.
144+
*
145+
* @param dirname The directory name in which the DAG file should reside
146+
* If it does not end with a directory separator it is appended.
147+
* @param filename The actual name of the file
148+
* @param filename_length The length of the filename in bytes
149+
* @return A char* containing the full name. User must deallocate.
150+
*/
151+
char* ethash_io_create_filename(
152+
char const* dirname,
153+
char const* filename,
154+
size_t filename_length
155+
);
156+
157+
/**
158+
* Gets the default directory name for the DAG depending on the system
159+
*
160+
* The spec defining this directory is here: https://github.com/ethereum/wiki/wiki/Ethash-DAG
161+
*
162+
* @param[out] strbuf A string buffer of sufficient size to keep the
163+
* null termninated string of the directory name
164+
* @param[in] buffsize Size of @a strbuf in bytes
165+
* @return true for success and false otherwise
166+
*/
167+
bool ethash_get_default_dirname(char* strbuf, size_t buffsize);
168+
139169
static inline bool ethash_io_mutable_name(
140170
uint32_t revision,
141171
ethash_h256_t const* seed_hash,
@@ -149,26 +179,6 @@ static inline bool ethash_io_mutable_name(
149179
return snprintf(output, DAG_MUTABLE_NAME_MAX_SIZE, "%u_%016" PRIx64, revision, hash) >= 0;
150180
}
151181

152-
static inline char* ethash_io_create_filename(
153-
char const* dirname,
154-
char const* filename,
155-
size_t filename_length
156-
)
157-
{
158-
size_t dirlen = strlen(dirname);
159-
// in C the cast is not needed, but a C++ compiler will complain for invalid conversion
160-
char* name = (char*)malloc(dirlen + filename_length + 1);
161-
if (!name) {
162-
return NULL;
163-
}
164-
165-
name[0] = '\0';
166-
ethash_strncat(name, dirlen + filename_length + 1, dirname, dirlen);
167-
ethash_strncat(name, dirlen + filename_length + 1, filename, filename_length);
168-
return name;
169-
}
170-
171-
172182
#ifdef __cplusplus
173183
}
174184
#endif

‎io_posix.c

+42
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,31 @@ int ethash_fileno(FILE *f)
4848
return fileno(f);
4949
}
5050

51+
char* ethash_io_create_filename(
52+
char const* dirname,
53+
char const* filename,
54+
size_t filename_length
55+
)
56+
{
57+
size_t dirlen = strlen(dirname);
58+
size_t dest_size = dirlen + filename_length + 1;
59+
if (dirname[dirlen] != '/') {
60+
dest_size += 1;
61+
}
62+
char* name = malloc(dest_size);
63+
if (!name) {
64+
return NULL;
65+
}
66+
67+
name[0] = '\0';
68+
ethash_strncat(name, dest_size, dirname, dirlen);
69+
if (dirname[dirlen] != '/') {
70+
ethash_strncat(name, dest_size, "/", 1);
71+
}
72+
ethash_strncat(name, dest_size, filename, filename_length);
73+
return name;
74+
}
75+
5176
bool ethash_file_size(FILE* f, size_t* ret_size)
5277
{
5378
struct stat st;
@@ -58,3 +83,20 @@ bool ethash_file_size(FILE* f, size_t* ret_size)
5883
*ret_size = st.st_size;
5984
return true;
6085
}
86+
87+
bool ethash_get_default_dirname(char* strbuf, size_t buffsize)
88+
{
89+
static const char dir_suffix[] = ".ethash/";
90+
strbuf[0] = '\0';
91+
char* home_dir = getenv("HOME");
92+
size_t len = strlen(home_dir);
93+
if (!ethash_strncat(strbuf, buffsize, home_dir, len)) {
94+
return false;
95+
}
96+
if (home_dir[len] != '/') {
97+
if (!ethash_strncat(strbuf, buffsize, "/", 1)) {
98+
return false;
99+
}
100+
}
101+
return ethash_strncat(strbuf, buffsize, dir_suffix, sizeof(dir_suffix));
102+
}

‎io_win32.c

+40
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <stdio.h>
2626
#include <sys/stat.h>
2727
#include <sys/types.h>
28+
#include <Shlobj.h>
2829

2930
FILE* ethash_fopen(char const* file_name, char const* mode)
3031
{
@@ -48,6 +49,31 @@ int ethash_fileno(FILE* f)
4849
return _fileno(f);
4950
}
5051

52+
char* ethash_io_create_filename(
53+
char const* dirname,
54+
char const* filename,
55+
size_t filename_length
56+
)
57+
{
58+
size_t dirlen = strlen(dirname);
59+
size_t dest_size = dirlen + filename_length + 1;
60+
if (dirname[dirlen] != '\\' || dirname[dirlen] != '/') {
61+
dest_size += 1;
62+
}
63+
char* name = malloc(dest_size);
64+
if (!name) {
65+
return NULL;
66+
}
67+
68+
name[0] = '\0';
69+
ethash_strncat(name, dest_size, dirname, dirlen);
70+
if (dirname[dirlen] != '\\' || dirname[dirlen] != '/') {
71+
ethash_strncat(name, dest_size, "\\", 1);
72+
}
73+
ethash_strncat(name, dest_size, filename, filename_length);
74+
return name;
75+
}
76+
5177
bool ethash_file_size(FILE* f, size_t* ret_size)
5278
{
5379
struct _stat st;
@@ -58,3 +84,17 @@ bool ethash_file_size(FILE* f, size_t* ret_size)
5884
*ret_size = st.st_size;
5985
return true;
6086
}
87+
88+
bool ethash_get_default_dirname(char* strbuf, size_t buffsize)
89+
{
90+
static const char dir_suffix[] = "Appdata\\Ethash\\";
91+
strbuf[0] = '\0';
92+
if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, 0, (WCHAR*)strbuf))) {
93+
return false;
94+
}
95+
if (!ethash_strncat(strbuf, buffsize, "\\", 1)) {
96+
return false;
97+
}
98+
99+
return ethash_strncat(strbuf, buffsize, dir_suffix, sizeof(dir_suffix));
100+
}

‎util.c ‎util_win32.c

File renamed without changes.

0 commit comments

Comments
 (0)
This repository has been archived.