• Péter Szilágyi's avatar
    Godeps, vendor: convert dependency management to trash (#3198) · 289b3071
    Péter Szilágyi authored
    This commit converts the dependency management from Godeps to the vendor
    folder, also switching the tool from godep to trash. Since the upstream tool
    lacks a few features proposed via a few PRs, until those PRs are merged in
    (if), use github.com/karalabe/trash.
    
    You can update dependencies via trash --update.
    
    All dependencies have been updated to their latest version.
    
    Parts of the build system are reworked to drop old notions of Godeps and
    invocation of the go vet command so that it doesn't run against the vendor
    folder, as that will just blow up during vetting.
    
    The conversion drops OpenCL (and hence GPU mining support) from ethash and our
    codebase. The short reasoning is that there's noone to maintain and having
    opencl libs in our deps messes up builds as go install ./... tries to build
    them, failing with unsatisfied link errors for the C OpenCL deps.
    
    golang.org/x/net/context is not vendored in. We expect it to be fetched by the
    user (i.e. using go get). To keep ci.go builds reproducible the package is
    "vendored" in build/_vendor.
    289b3071
io.h 7.3 KB
/*
  This file is part of ethash.

  ethash 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.

  ethash 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 ethash.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file io.h
 * @author Lefteris Karapetsas <lefteris@ethdev.com>
 * @date 2015
 */
#pragma once
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#ifdef __cplusplus
#define __STDC_FORMAT_MACROS 1
#endif
#include <inttypes.h>
#include "endian.h"
#include "ethash.h"

#ifdef __cplusplus
extern "C" {
#endif
// Maximum size for mutable part of DAG file name
// 6 is for "full-R", the suffix of the filename
// 10 is for maximum number of digits of a uint32_t (for REVISION)
// 1 is for - and 16 is for the first 16 hex digits for first 8 bytes of
// the seedhash and last 1 is for the null terminating character
// Reference: https://github.com/ethereum/wiki/wiki/Ethash-DAG
#define DAG_MUTABLE_NAME_MAX_SIZE (6 + 10 + 1 + 16 + 1)
/// Possible return values of @see ethash_io_prepare
enum ethash_io_rc {
	ETHASH_IO_FAIL = 0,           ///< There has been an IO failure
	ETHASH_IO_MEMO_SIZE_MISMATCH, ///< DAG with revision/hash match, but file size was wrong.
	ETHASH_IO_MEMO_MISMATCH,      ///< The DAG file did not exist or there was revision/hash mismatch
	ETHASH_IO_MEMO_MATCH,         ///< DAG file existed and revision/hash matched. No need to do anything
};

// small hack for windows. I don't feel I should use va_args and forward just
// to have this one function properly cross-platform abstracted
#if defined(_WIN32) && !defined(__GNUC__)
#define snprintf(...) sprintf_s(__VA_ARGS__)
#endif

/**
 * Logs a critical error in important parts of ethash. Should mostly help
 * figure out what kind of problem (I/O, memory e.t.c.) causes a NULL
 * ethash_full_t
 */
#ifdef ETHASH_PRINT_CRITICAL_OUTPUT
#define ETHASH_CRITICAL(...)							\
	do													\
	{													\
		printf("ETHASH CRITICAL ERROR: "__VA_ARGS__);	\
		printf("\n");									\
		fflush(stdout);									\
	} while (0)
#else
#define ETHASH_CRITICAL(...)          
#endif

/**
 * Prepares io for ethash
 *
 * Create the DAG directory and the DAG file if they don't exist.
 *
 * @param[in] dirname        A null terminated c-string of the path of the ethash
 *                           data directory. If it does not exist it's created.
 * @param[in] seedhash       The seedhash of the current block number, used in the
 *                           naming of the file as can be seen from the spec at:
 *                           https://github.com/ethereum/wiki/wiki/Ethash-DAG
 * @param[out] output_file   If there was no failure then this will point to an open
 *                           file descriptor. User is responsible for closing it.
 *                           In the case of memo match then the file is open on read
 *                           mode, while on the case of mismatch a new file is created
 *                           on write mode
 * @param[in] file_size      The size that the DAG file should have on disk
 * @param[out] force_create  If true then there is no check to see if the file
 *                           already exists
 * @return                   For possible return values @see enum ethash_io_rc
 */
enum ethash_io_rc ethash_io_prepare(
	char const* dirname,
	ethash_h256_t const seedhash,
	FILE** output_file,
	uint64_t file_size,
	bool force_create
);

/**
 * An fopen wrapper for no-warnings crossplatform fopen.
 *
 * Msvc compiler considers fopen to be insecure and suggests to use their
 * alternative. This is a wrapper for this alternative. Another way is to
 * #define _CRT_SECURE_NO_WARNINGS, but disabling all security warnings does
 * not sound like a good idea.
 *
 * @param file_name        The path to the file to open
 * @param mode             Opening mode. Check fopen()
 * @return                 The FILE* or NULL in failure
 */
FILE* ethash_fopen(char const* file_name, char const* mode);

/**
 * An strncat wrapper for no-warnings crossplatform strncat.
 *
 * Msvc compiler considers strncat to be insecure and suggests to use their
 * alternative. This is a wrapper for this alternative. Another way is to
 * #define _CRT_SECURE_NO_WARNINGS, but disabling all security warnings does
 * not sound like a good idea.
 *
 * @param des              Destination buffer
 * @param dest_size        Maximum size of the destination buffer. This is the
 *                         extra argument for the MSVC secure strncat
 * @param src              Souce buffer
 * @param count            Number of bytes to copy from source
 * @return                 If all is well returns the dest buffer. If there is an
 *                         error returns NULL
 */
char* ethash_strncat(char* dest, size_t dest_size, char const* src, size_t count);

/**
 * A cross-platform mkdir wrapper to create a directory or assert it's there
 *
 * @param dirname        The full path of the directory to create
 * @return               true if the directory was created or if it already
 *                       existed
 */
bool ethash_mkdir(char const* dirname);

/**
 * Get a file's size
 *
 * @param[in] f        The open file stream whose size to get
 * @param[out] size    Pass a size_t by reference to contain the file size
 * @return             true in success and false if there was a failure
 */
bool ethash_file_size(FILE* f, size_t* ret_size);

/**
 * Get a file descriptor number from a FILE stream
 *
 * @param f            The file stream whose fd to get
 * @return             Platform specific fd handler
 */
int ethash_fileno(FILE* f);

/**
 * Create the filename for the DAG.
 *
 * @param dirname            The directory name in which the DAG file should reside
 *                           If it does not end with a directory separator it is appended.
 * @param filename           The actual name of the file
 * @param filename_length    The length of the filename in bytes
 * @return                   A char* containing the full name. User must deallocate.
 */
char* ethash_io_create_filename(
	char const* dirname,
	char const* filename,
	size_t filename_length
);

/**
 * Gets the default directory name for the DAG depending on the system
 *
 * The spec defining this directory is here: https://github.com/ethereum/wiki/wiki/Ethash-DAG
 *
 * @param[out] strbuf          A string buffer of sufficient size to keep the
 *                             null termninated string of the directory name
 * @param[in]  buffsize        Size of @a strbuf in bytes
 * @return                     true for success and false otherwise
 */
bool ethash_get_default_dirname(char* strbuf, size_t buffsize);

static inline bool ethash_io_mutable_name(
	uint32_t revision,
	ethash_h256_t const* seed_hash,
	char* output
)
{
    uint64_t hash = *((uint64_t*)seed_hash);
#if LITTLE_ENDIAN == BYTE_ORDER
    hash = ethash_swap_u64(hash);
#endif
    return snprintf(output, DAG_MUTABLE_NAME_MAX_SIZE, "full-R%u-%016" PRIx64, revision, hash) >= 0;
}

#ifdef __cplusplus
}
#endif