first commit: the user sdk of the HCloud

This commit is contained in:
Hua Zhichao 2019-08-09 06:50:18 +00:00
parent f897b1c994
commit 4e0ff5c91d
39 changed files with 4126 additions and 0 deletions

3
.gitignore vendored
View File

@ -11,3 +11,6 @@
# .nfs files are created when an open file is removed but is still being accessed # .nfs files are created when an open file is removed but is still being accessed
.nfs* .nfs*
*.swp

65
Makefile Normal file
View File

@ -0,0 +1,65 @@
SGX_SDK ?= /opt/intel/sgxsdk
#OPENSSL_HOME ?= /opt/openssl/1.1.0i/
TEEX_SSL_HOME ?= ./deps/TEEX-SSL
PUBLIC_CHAIN_SDK_HOME ?= ./deps/PublicChainSDK
CC := gcc
CXX := g++
AR := ar
C_FLAGS := -g -Wall -I./include -I$(SGX_SDK)/include -I$(TEEX_SSL_HOME)/include -I$(PUBLIC_CHAIN_SDK_HOME)/include
#C_FLAGS += -fsanitize=address
ifneq ($(OPENSSL_HOME), )
C_FLAGS += -I$(OPENSSL_HOME)/include
endif
CPP_FLAGS := $(C_FLAGS) -std=c++11
LINK_FLAGS := -L./lib -L$(TEEX_SSL_HOME)/lib -L$(PUBLIC_CHAIN_SDK_HOME)/lib -lteex_ssl -lcurl -lpublicchain -lethrpc -lcurl -lcjson -luuid
#LINK_FLAGS += -fsanitize=address
ifneq ($(OPENSSL_HOME), )
LINK_FLAGS += -L$(OPENSSL_HOME)/lib -lcrypto
else
LINK_FLAGS += -lcrypto
endif
#LINK_FLAGS := -L../Lib -lteex_ssl -l:libcrypto.a -lcurl -lpthread -ldl
LIB_NAME := ./lib/libteex.a
TEST_C_FILES := $(wildcard tests/*.c)
TEST_C_OBJECTS := $(TEST_C_FILES:.c=.o)
TEST_CPP_FILES := $(wildcard tests/*.cpp)
TEST_CPP_OBJECTS := $(TEST_CPP_FILES:.cpp=.o)
TEST_LINK_FLAGS := -L./lib -lteex $(LINK_FLAGS)
LIB_C_FILES := $(wildcard src/*.c)
LIB_C_OBJECTS := $(LIB_C_FILES:.c=.o)
LIB_CPP_FILES := $(wildcard src/*.cpp)
LIB_CPP_OBJECTS := $(LIB_CPP_FILES:.cpp=.o)
all: $(LIB_NAME) test
libs: $(LIB_NAME)
#%.o: %.c
# $(CC) $(C_FLAGS) -c $< -o $@
%.o: %.cpp
$(CXX) $(CPP_FLAGS) -c $< -o $@
$(LIB_NAME): $(LIB_C_OBJECTS) $(LIB_CPP_OBJECTS)
$(AR) -rc $@ $^
test: $(TEST_C_OBJECTS) $(TEST_CPP_OBJECTS)
$(CXX) $^ -o $@ $(TEST_LINK_FLAGS)
clean:
rm -f $(LIB_NAME) test $(LIB_C_OBJECTS) $(LIB_CPP_OBJECTS) $(TEST_C_OBJECTS) $(TEST_CPP_OBJECTS)

View File

@ -0,0 +1,150 @@
#ifndef PUBLICCHAIN_H
#define PUBLICCHAIN_H
#include<stdint.h>
#include"ethrpc.h"
#include"ethrpc_type.h"
#define MAX_DESC_LENGTH 128
using namespace std;
typedef struct _dataBlock{
char* dataID;
Address owner;
Hash data_hash;
uint256 size;
uint256 price;
char* url; // end with '\0'
uint32_t score;
} Datablock;
typedef struct _service{
char* servideID;
Address sp_addr; //Holds a 20 byte value (size of an Ethereum address)
Address service_pk;
char* codeHash;
uint256 price;
uint256 worker_feerate;
char* desc; //the description of the service(can be a url)
uint32_t data_num;
char** bound_data_list;
} Service;
typedef struct _task{
char* taskID;
Address pk_user;
char* servideID;
uint32_t timeout;
uint256 payment; //price for teex
Hash input_hash;
uint32_t status;
uint32_t data_num;
char** bound_data_list;
} Task;
typedef struct _receipt{
char* taskID;
uint32_t workerNum;
Address* workerList;
uint32_t* countList;
unsigned char* sig;
uint32_t dp_num;
uint32_t* dp_status_list;
} Receipt;
typedef struct _tasklist{
uint32_t size;
Task* tasks;
} TaskList;
typedef struct _servicelist{
uint32_t size;
Service* services;
} ServiceList;
class PublicChain{
public:
PublicChain(const char* url, const char* Bounty_Contract_Address, const char* TEEX_Contract_Address, const char* sk, const char* pk);
~PublicChain();
uint32_t getServiceLength();
uint32_t getServiceList(ServiceList& res);
uint32_t getServiceByID(char* id, Service& res);
uint32_t newService(Service* service);
uint32_t getTaskListByUser(Address addr, TaskList& res);
uint32_t getTaskByID(char* id, Task& res);
uint32_t newTask(Task* task);
uint32_t verifyTask(Receipt* receipt);
uint32_t abortTask(Receipt* receipt);
uint32_t recallTask(char* taskID);
uint32_t checkService(string txnhash, Service* service);
char* getBalance(const char* address);
uint32_t newDataBlock(Datablock* dataBlock);
uint32_t getDataBlockByID(char* id, Datablock& dataBlock);
// variables
uint32_t status;
ETHRPC* ethrpc;
char* pk = new char[43];
char* TEEX_Contract_Address = new char[43];
char* Bounty_Contract_Address = new char[43];
private:
uint32_t getRandom();
uint32_t approveToken(Address from, uint256 amount);
};
#endif /* PUBLICCHAIN_H */

34
deps/PublicChainSDK/include/ethrpc.h vendored Normal file
View File

@ -0,0 +1,34 @@
#ifndef ETHPRC_H
#define ETHPRC_H
#include <iostream>
#include "ethrpc_type.h"
#include "rpc.h"
using namespace std;
class ETHRPC{
public:
ETHRPC(const char* url);
// ~ETHRPC();
ResultCode web3_sha3(const char* raw_ascii, string *res);
ResultCode eth_call(const char* contract_addr, const char* func_spec, int paras_count, int return_count, ...);
ResultCode eth_send(const char* contract_addr, const char* from_pk, int gas, int gas_price, int value, const char* func_spec, string* txnhash, int paras_count, ...);
ResultCode eth_getTransactionReceipt(const char* txnhash, string *res);
ResultCode personal_importRawKey(const char* private_key, const char* passphrase, string *res);
ResultCode personal_lockAccount(const char* address, const char* passphrase, int duration = 300);
private:
RPC* rpc;
};
#endif

View File

@ -0,0 +1,209 @@
#ifndef ETHRPC_TYPE_H
#define ETHRPC_TYPE_H
#include <stdint.h>
/**
* ================================================================================================================================
* TYPE used in JSON-RPC
*
* ================================================================================================================================
*/
#define UINT32 1
#define UINT32_ARRAY 2
#define CHAR_ARRAY 3
#define ADDRESS 4
#define ADDRESS_ARRAY 5
#define FLOAT 6
#define FLOAT_ARRAY 7
#define BYTES32 8
#define BYTES32_ARRAY 9
#define UINT256 10
#define UINT256_ARRAY 11
#define BYTES 12
/**
* ================================================================================================================================
* RETURN VALUES
*
* ================================================================================================================================
*/
// typedef enum {
// CURLE_OK = 0,
// CURLE_UNSUPPORTED_PROTOCOL, /* 1 */
// CURLE_FAILED_INIT, /* 2 */
// CURLE_URL_MALFORMAT, /* 3 */
// CURLE_NOT_BUILT_IN, /* 4 - [was obsoleted in August 2007 for
// 7.17.0, reused in April 2011 for 7.21.5] */
// CURLE_COULDNT_RESOLVE_PROXY, /* 5 */
// CURLE_COULDNT_RESOLVE_HOST, /* 6 */
// CURLE_COULDNT_CONNECT, /* 7 */
// CURLE_FTP_WEIRD_SERVER_REPLY, /* 8 */
// CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server
// due to lack of access - when login fails
// this is not returned. */
// CURLE_FTP_ACCEPT_FAILED, /* 10 - [was obsoleted in April 2006 for
// 7.15.4, reused in Dec 2011 for 7.24.0]*/
// CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */
// CURLE_FTP_ACCEPT_TIMEOUT, /* 12 - timeout occurred accepting server
// [was obsoleted in August 2007 for 7.17.0,
// reused in Dec 2011 for 7.24.0]*/
// CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */
// CURLE_FTP_WEIRD_227_FORMAT, /* 14 */
// CURLE_FTP_CANT_GET_HOST, /* 15 */
// CURLE_HTTP2, /* 16 - A problem in the http2 framing layer.
// [was obsoleted in August 2007 for 7.17.0,
// reused in July 2014 for 7.38.0] */
// CURLE_FTP_COULDNT_SET_TYPE, /* 17 */
// CURLE_PARTIAL_FILE, /* 18 */
// CURLE_FTP_COULDNT_RETR_FILE, /* 19 */
// CURLE_OBSOLETE20, /* 20 - NOT USED */
// CURLE_QUOTE_ERROR, /* 21 - quote command failure */
// CURLE_HTTP_RETURNED_ERROR, /* 22 */
// CURLE_WRITE_ERROR, /* 23 */
// CURLE_OBSOLETE24, /* 24 - NOT USED */
// CURLE_UPLOAD_FAILED, /* 25 - failed upload "command" */
// CURLE_READ_ERROR, /* 26 - couldn't open/read from file */
// CURLE_OUT_OF_MEMORY, /* 27 */
// /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error
// instead of a memory allocation error if CURL_DOES_CONVERSIONS
// is defined
// */
// CURLE_OPERATION_TIMEDOUT, /* 28 - the timeout time was reached */
// CURLE_OBSOLETE29, /* 29 - NOT USED */
// CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */
// CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */
// CURLE_OBSOLETE32, /* 32 - NOT USED */
// CURLE_RANGE_ERROR, /* 33 - RANGE "command" didn't work */
// CURLE_HTTP_POST_ERROR, /* 34 */
// CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */
// CURLE_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */
// CURLE_FILE_COULDNT_READ_FILE, /* 37 */
// CURLE_LDAP_CANNOT_BIND, /* 38 */
// CURLE_LDAP_SEARCH_FAILED, /* 39 */
// CURLE_OBSOLETE40, /* 40 - NOT USED */
// CURLE_FUNCTION_NOT_FOUND, /* 41 */
// CURLE_ABORTED_BY_CALLBACK, /* 42 */
// CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */
// CURLE_OBSOLETE44, /* 44 - NOT USED */
// CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */
// CURLE_OBSOLETE46, /* 46 - NOT USED */
// CURLE_TOO_MANY_REDIRECTS , /* 47 - catch endless re-direct loops */
// CURLE_UNKNOWN_OPTION, /* 48 - User specified an unknown option */
// CURLE_TELNET_OPTION_SYNTAX , /* 49 - Malformed telnet option */
// CURLE_OBSOLETE50, /* 50 - NOT USED */
// CURLE_PEER_FAILED_VERIFICATION, /* 51 - peer's certificate or fingerprint
// wasn't verified fine */
// CURLE_GOT_NOTHING, /* 52 - when this is a specific error */
// CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */
// CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as
// default */
// CURLE_SEND_ERROR, /* 55 - failed sending network data */
// CURLE_RECV_ERROR, /* 56 - failure in receiving network data */
// CURLE_OBSOLETE57, /* 57 - NOT IN USE */
// CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */
// CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */
// CURLE_SSL_CACERT, /* 60 - problem with the CA cert (path?) */
// CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized/bad encoding */
// CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */
// CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */
// CURLE_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */
// CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind
// that failed */
// CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */
// CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not
// accepted and we failed to login */
// CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */
// CURLE_TFTP_PERM, /* 69 - permission problem on server */
// CURLE_REMOTE_DISK_FULL, /* 70 - out of disk space on server */
// CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */
// CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */
// CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */
// CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */
// CURLE_CONV_FAILED, /* 75 - conversion failed */
// CURLE_CONV_REQD, /* 76 - caller must register conversion
// callbacks using curl_easy_setopt options
// CURLOPT_CONV_FROM_NETWORK_FUNCTION,
// CURLOPT_CONV_TO_NETWORK_FUNCTION, and
// CURLOPT_CONV_FROM_UTF8_FUNCTION */
// CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing
// or wrong format */
// CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */
// CURLE_SSH, /* 79 - error from the SSH layer, somewhat
// generic so the error message will be of
// interest when this has happened */
// CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL
// connection */
// CURLE_AGAIN, /* 81 - socket is not ready for send/recv,
// wait till it's ready and try again (Added
// in 7.18.2) */
// CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or
// wrong format (Added in 7.19.0) */
// CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in
// 7.19.0) */
// CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */
// CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */
// CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Ids */
// CURLE_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */
// CURLE_CHUNK_FAILED, /* 88 - chunk callback reported error */
// CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the
// session will be queued */
// CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not
// match */
// CURLE_SSL_INVALIDCERTSTATUS, /* 91 - invalid certificate status */
// CURL_LAST /* never use! */
// } CURLcode;
#define FOREACH_VALUE(X) \
X(0, SUCCESS, "ETH RPC returned successfully") \
X(1, BAD_PARAMS, "Bad parameters") \
X(2, CURL_NO_RETURN, "Curl no returns") \
X(3, CURL_EMPTY_RETURN, "Curl empry returns") \
X(4, CJSON_PARSE_FAIL, "cJSON parse faile") \
X(5, INVALID_JSON, "Invalid json") \
X(6, INVALID_SHA3_RETRUN, "Invalid sha3 return") \
X(1000, CURL_FAIL, "CURL failed") \
X(100000, ETH_ERROR, "Ethereum error") \
X(132700, ETH_PAESE_ERROR, "Ethereum parse error") \
X(132600, ETH_INVALID_REQUEST, "Ethereum invalid request") \
X(132601, ETH_METHOD_NOT_FOUND, "Ethereum method not found") \
X(132602, ETH_INVALID_PARAMS, "Ethereum invalid params") \
X(132603, ETH_INTERNAL_ERROR, "Ethereum error") \
X(132000, ETH_SERVER_ERROR, "Ethereum server error") \
X(100001, ETH_UNAUTHORIZED, "Ethereum unauthorized") \
X(100002, ETH_ACTION_NOT_ALLOWED, "Ethereum action not allowed") \
X(100003, ETH_EXECUTION_ERROR, "Ethereum execution error") \
#define GENERATE_ENUM(ID, NAME, TEXT) NAME = ID,
#define RETURN_VALUES_TEXT(ID, NAME, TEXT) case ID: return TEXT;
enum RETURN_VALUES{
FOREACH_VALUE(GENERATE_ENUM)
};
extern const char *RETURN_MESSAGE(int id);
typedef uint32_t ResultCode;
/**
* ================================================================================================================================
* ASCII-presented Hex String
* Require 2x space
* ================================================================================================================================
*/
typedef char uint256[64];
typedef char Hash[64];
typedef char Address[40];
typedef char Bytes32[64];
#endif

View File

@ -0,0 +1,19 @@
#ifndef KECCAK_FIPS202_H
#define KECCAK_FIPS202_H
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdint.h>
#include <stdlib.h>
#define decshake(bits) \
int shake##bits(uint8_t*, size_t, const uint8_t*, size_t);
#define decsha3(bits) \
int sha3_##bits(uint8_t*, size_t, const uint8_t*, size_t);
decshake(128)
decshake(256)
decsha3(224)
decsha3(256)
decsha3(384)
decsha3(512)
#endif

17
deps/PublicChainSDK/include/log.h vendored Normal file
View File

@ -0,0 +1,17 @@
#ifndef LOG_H
#define LOG_H
#include <stdio.h>
#include <stdlib.h>
// #define __TEEX_DEBUG__
#ifdef __TEEX_DEBUG__
#define DEBUG(format,...) printf("\033[36m[TEEX-DEBUG]File: " __FILE__ ", Line: %04d: " format "\033[0m\n", __LINE__ , ##__VA_ARGS__)
#else
#define DEBUG(format,...)
#endif
#endif

41
deps/PublicChainSDK/include/rpc.h vendored Normal file
View File

@ -0,0 +1,41 @@
#ifndef RPC_H
#define RPC_H
#include <iostream>
#include <stdint.h>
#include <cjson/cJSON.h>
#include "ethrpc_type.h"
#include <curl/curl.h>
using namespace std;
class RPC{
public:
RPC(const char* url);
~RPC();
ResultCode call_rpc(int id,
const char* method,
cJSON *param,
string *result);
private:
const char* url; //default
CURL* curl;
struct curl_slist* headers;
};
#endif

654
deps/PublicChainSDK/include/secp256k1.h vendored Normal file
View File

@ -0,0 +1,654 @@
#ifndef SECP256K1_H
#define SECP256K1_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
/* These rules specify the order of arguments in API calls:
*
* 1. Context pointers go first, followed by output arguments, combined
* output/input arguments, and finally input-only arguments.
* 2. Array lengths always immediately the follow the argument whose length
* they describe, even if this violates rule 1.
* 3. Within the OUT/OUTIN/IN groups, pointers to data that is typically generated
* later go first. This means: signatures, public nonces, private nonces,
* messages, public keys, secret keys, tweaks.
* 4. Arguments that are not data pointers go last, from more complex to less
* complex: function pointers, algorithm names, messages, void pointers,
* counts, flags, booleans.
* 5. Opaque data pointers follow the function pointer they are to be passed to.
*/
/** Opaque data structure that holds context information (precomputed tables etc.).
*
* The purpose of context structures is to cache large precomputed data tables
* that are expensive to construct, and also to maintain the randomization data
* for blinding.
*
* Do not create a new context object for each operation, as construction is
* far slower than all other API calls (~100 times slower than an ECDSA
* verification).
*
* A constructed context can safely be used from multiple threads
* simultaneously, but API call that take a non-const pointer to a context
* need exclusive access to it. In particular this is the case for
* secp256k1_context_destroy and secp256k1_context_randomize.
*
* Regarding randomization, either do it once at creation time (in which case
* you do not need any locking for the other calls), or use a read-write lock.
*/
typedef struct secp256k1_context_struct secp256k1_context;
/** Opaque data structure that holds rewriteable "scratch space"
*
* The purpose of this structure is to replace dynamic memory allocations,
* because we target architectures where this may not be available. It is
* essentially a resizable (within specified parameters) block of bytes,
* which is initially created either by memory allocation or TODO as a pointer
* into some fixed rewritable space.
*
* Unlike the context object, this cannot safely be shared between threads
* without additional synchronization logic.
*/
typedef struct secp256k1_scratch_space_struct secp256k1_scratch_space;
/** Opaque data structure that holds a parsed and valid public key.
*
* The exact representation of data inside is implementation defined and not
* guaranteed to be portable between different platforms or versions. It is
* however guaranteed to be 64 bytes in size, and can be safely copied/moved.
* If you need to convert to a format suitable for storage, transmission, or
* comparison, use secp256k1_ec_pubkey_serialize and secp256k1_ec_pubkey_parse.
*/
typedef struct {
unsigned char data[64];
} secp256k1_pubkey;
/** Opaque data structured that holds a parsed ECDSA signature.
*
* The exact representation of data inside is implementation defined and not
* guaranteed to be portable between different platforms or versions. It is
* however guaranteed to be 64 bytes in size, and can be safely copied/moved.
* If you need to convert to a format suitable for storage, transmission, or
* comparison, use the secp256k1_ecdsa_signature_serialize_* and
* secp256k1_ecdsa_signature_parse_* functions.
*/
typedef struct {
unsigned char data[64];
} secp256k1_ecdsa_signature;
/** A pointer to a function to deterministically generate a nonce.
*
* Returns: 1 if a nonce was successfully generated. 0 will cause signing to fail.
* Out: nonce32: pointer to a 32-byte array to be filled by the function.
* In: msg32: the 32-byte message hash being verified (will not be NULL)
* key32: pointer to a 32-byte secret key (will not be NULL)
* algo16: pointer to a 16-byte array describing the signature
* algorithm (will be NULL for ECDSA for compatibility).
* data: Arbitrary data pointer that is passed through.
* attempt: how many iterations we have tried to find a nonce.
* This will almost always be 0, but different attempt values
* are required to result in a different nonce.
*
* Except for test cases, this function should compute some cryptographic hash of
* the message, the algorithm, the key and the attempt.
*/
typedef int (*secp256k1_nonce_function)(
unsigned char *nonce32,
const unsigned char *msg32,
const unsigned char *key32,
const unsigned char *algo16,
void *data,
unsigned int attempt
);
# if !defined(SECP256K1_GNUC_PREREQ)
# if defined(__GNUC__)&&defined(__GNUC_MINOR__)
# define SECP256K1_GNUC_PREREQ(_maj,_min) \
((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
# else
# define SECP256K1_GNUC_PREREQ(_maj,_min) 0
# endif
# endif
# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
# if SECP256K1_GNUC_PREREQ(2,7)
# define SECP256K1_INLINE __inline__
# elif (defined(_MSC_VER))
# define SECP256K1_INLINE __inline
# else
# define SECP256K1_INLINE
# endif
# else
# define SECP256K1_INLINE inline
# endif
#ifndef SECP256K1_API
# if defined(_WIN32)
# ifdef SECP256K1_BUILD
# define SECP256K1_API __declspec(dllexport)
# else
# define SECP256K1_API
# endif
# elif defined(__GNUC__) && defined(SECP256K1_BUILD)
# define SECP256K1_API __attribute__ ((visibility ("default")))
# else
# define SECP256K1_API
# endif
#endif
/**Warning attributes
* NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out
* some paranoid null checks. */
# if defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4)
# define SECP256K1_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
# else
# define SECP256K1_WARN_UNUSED_RESULT
# endif
# if !defined(SECP256K1_BUILD) && defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4)
# define SECP256K1_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x)))
# else
# define SECP256K1_ARG_NONNULL(_x)
# endif
/** All flags' lower 8 bits indicate what they're for. Do not use directly. */
#define SECP256K1_FLAGS_TYPE_MASK ((1 << 8) - 1)
#define SECP256K1_FLAGS_TYPE_CONTEXT (1 << 0)
#define SECP256K1_FLAGS_TYPE_COMPRESSION (1 << 1)
/** The higher bits contain the actual data. Do not use directly. */
#define SECP256K1_FLAGS_BIT_CONTEXT_VERIFY (1 << 8)
#define SECP256K1_FLAGS_BIT_CONTEXT_SIGN (1 << 9)
#define SECP256K1_FLAGS_BIT_COMPRESSION (1 << 8)
/** Flags to pass to secp256k1_context_create. */
#define SECP256K1_CONTEXT_VERIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY)
#define SECP256K1_CONTEXT_SIGN (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN)
#define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT)
/** Flag to pass to secp256k1_ec_pubkey_serialize and secp256k1_ec_privkey_export. */
#define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION)
#define SECP256K1_EC_UNCOMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION)
/** Prefix byte used to tag various encoded curvepoints for specific purposes */
#define SECP256K1_TAG_PUBKEY_EVEN 0x02
#define SECP256K1_TAG_PUBKEY_ODD 0x03
#define SECP256K1_TAG_PUBKEY_UNCOMPRESSED 0x04
#define SECP256K1_TAG_PUBKEY_HYBRID_EVEN 0x06
#define SECP256K1_TAG_PUBKEY_HYBRID_ODD 0x07
/** Create a secp256k1 context object.
*
* Returns: a newly created context object.
* In: flags: which parts of the context to initialize.
*
* See also secp256k1_context_randomize.
*/
SECP256K1_API secp256k1_context* secp256k1_context_create(
unsigned int flags
) SECP256K1_WARN_UNUSED_RESULT;
/** Copies a secp256k1 context object.
*
* Returns: a newly created context object.
* Args: ctx: an existing context to copy (cannot be NULL)
*/
SECP256K1_API secp256k1_context* secp256k1_context_clone(
const secp256k1_context* ctx
) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT;
/** Destroy a secp256k1 context object.
*
* The context pointer may not be used afterwards.
* Args: ctx: an existing context to destroy (cannot be NULL)
*/
SECP256K1_API void secp256k1_context_destroy(
secp256k1_context* ctx
);
/** Set a callback function to be called when an illegal argument is passed to
* an API call. It will only trigger for violations that are mentioned
* explicitly in the header.
*
* The philosophy is that these shouldn't be dealt with through a
* specific return value, as calling code should not have branches to deal with
* the case that this code itself is broken.
*
* On the other hand, during debug stage, one would want to be informed about
* such mistakes, and the default (crashing) may be inadvisable.
* When this callback is triggered, the API function called is guaranteed not
* to cause a crash, though its return value and output arguments are
* undefined.
*
* Args: ctx: an existing context object (cannot be NULL)
* In: fun: a pointer to a function to call when an illegal argument is
* passed to the API, taking a message and an opaque pointer
* (NULL restores a default handler that calls abort).
* data: the opaque pointer to pass to fun above.
*/
SECP256K1_API void secp256k1_context_set_illegal_callback(
secp256k1_context* ctx,
void (*fun)(const char* message, void* data),
const void* data
) SECP256K1_ARG_NONNULL(1);
/** Set a callback function to be called when an internal consistency check
* fails. The default is crashing.
*
* This can only trigger in case of a hardware failure, miscompilation,
* memory corruption, serious bug in the library, or other error would can
* otherwise result in undefined behaviour. It will not trigger due to mere
* incorrect usage of the API (see secp256k1_context_set_illegal_callback
* for that). After this callback returns, anything may happen, including
* crashing.
*
* Args: ctx: an existing context object (cannot be NULL)
* In: fun: a pointer to a function to call when an internal error occurs,
* taking a message and an opaque pointer (NULL restores a default
* handler that calls abort).
* data: the opaque pointer to pass to fun above.
*/
SECP256K1_API void secp256k1_context_set_error_callback(
secp256k1_context* ctx,
void (*fun)(const char* message, void* data),
const void* data
) SECP256K1_ARG_NONNULL(1);
/** Create a secp256k1 scratch space object.
*
* Returns: a newly created scratch space.
* Args: ctx: an existing context object (cannot be NULL)
* In: max_size: maximum amount of memory to allocate
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_scratch_space* secp256k1_scratch_space_create(
const secp256k1_context* ctx,
size_t max_size
) SECP256K1_ARG_NONNULL(1);
/** Destroy a secp256k1 scratch space.
*
* The pointer may not be used afterwards.
* Args: scratch: space to destroy
*/
SECP256K1_API void secp256k1_scratch_space_destroy(
secp256k1_scratch_space* scratch
);
/** Parse a variable-length public key into the pubkey object.
*
* Returns: 1 if the public key was fully valid.
* 0 if the public key could not be parsed or is invalid.
* Args: ctx: a secp256k1 context object.
* Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a
* parsed version of input. If not, its value is undefined.
* In: input: pointer to a serialized public key
* inputlen: length of the array pointed to by input
*
* This function supports parsing compressed (33 bytes, header byte 0x02 or
* 0x03), uncompressed (65 bytes, header byte 0x04), or hybrid (65 bytes, header
* byte 0x06 or 0x07) format public keys.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse(
const secp256k1_context* ctx,
secp256k1_pubkey* pubkey,
const unsigned char *input,
size_t inputlen
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Serialize a pubkey object into a serialized byte sequence.
*
* Returns: 1 always.
* Args: ctx: a secp256k1 context object.
* Out: output: a pointer to a 65-byte (if compressed==0) or 33-byte (if
* compressed==1) byte array to place the serialized key
* in.
* In/Out: outputlen: a pointer to an integer which is initially set to the
* size of output, and is overwritten with the written
* size.
* In: pubkey: a pointer to a secp256k1_pubkey containing an
* initialized public key.
* flags: SECP256K1_EC_COMPRESSED if serialization should be in
* compressed format, otherwise SECP256K1_EC_UNCOMPRESSED.
*/
SECP256K1_API int secp256k1_ec_pubkey_serialize(
const secp256k1_context* ctx,
unsigned char *output,
size_t *outputlen,
const secp256k1_pubkey* pubkey,
unsigned int flags
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Parse an ECDSA signature in compact (64 bytes) format.
*
* Returns: 1 when the signature could be parsed, 0 otherwise.
* Args: ctx: a secp256k1 context object
* Out: sig: a pointer to a signature object
* In: input64: a pointer to the 64-byte array to parse
*
* The signature must consist of a 32-byte big endian R value, followed by a
* 32-byte big endian S value. If R or S fall outside of [0..order-1], the
* encoding is invalid. R and S with value 0 are allowed in the encoding.
*
* After the call, sig will always be initialized. If parsing failed or R or
* S are zero, the resulting sig value is guaranteed to fail validation for any
* message and public key.
*/
SECP256K1_API int secp256k1_ecdsa_signature_parse_compact(
const secp256k1_context* ctx,
secp256k1_ecdsa_signature* sig,
const unsigned char *input64
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Parse a DER ECDSA signature.
*
* Returns: 1 when the signature could be parsed, 0 otherwise.
* Args: ctx: a secp256k1 context object
* Out: sig: a pointer to a signature object
* In: input: a pointer to the signature to be parsed
* inputlen: the length of the array pointed to be input
*
* This function will accept any valid DER encoded signature, even if the
* encoded numbers are out of range.
*
* After the call, sig will always be initialized. If parsing failed or the
* encoded numbers are out of range, signature validation with it is
* guaranteed to fail for every message and public key.
*/
SECP256K1_API int secp256k1_ecdsa_signature_parse_der(
const secp256k1_context* ctx,
secp256k1_ecdsa_signature* sig,
const unsigned char *input,
size_t inputlen
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Serialize an ECDSA signature in DER format.
*
* Returns: 1 if enough space was available to serialize, 0 otherwise
* Args: ctx: a secp256k1 context object
* Out: output: a pointer to an array to store the DER serialization
* In/Out: outputlen: a pointer to a length integer. Initially, this integer
* should be set to the length of output. After the call
* it will be set to the length of the serialization (even
* if 0 was returned).
* In: sig: a pointer to an initialized signature object
*/
SECP256K1_API int secp256k1_ecdsa_signature_serialize_der(
const secp256k1_context* ctx,
unsigned char *output,
size_t *outputlen,
const secp256k1_ecdsa_signature* sig
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Serialize an ECDSA signature in compact (64 byte) format.
*
* Returns: 1
* Args: ctx: a secp256k1 context object
* Out: output64: a pointer to a 64-byte array to store the compact serialization
* In: sig: a pointer to an initialized signature object
*
* See secp256k1_ecdsa_signature_parse_compact for details about the encoding.
*/
SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact(
const secp256k1_context* ctx,
unsigned char *output64,
const secp256k1_ecdsa_signature* sig
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Verify an ECDSA signature.
*
* Returns: 1: correct signature
* 0: incorrect or unparseable signature
* Args: ctx: a secp256k1 context object, initialized for verification.
* In: sig: the signature being verified (cannot be NULL)
* msg32: the 32-byte message hash being verified (cannot be NULL)
* pubkey: pointer to an initialized public key to verify with (cannot be NULL)
*
* To avoid accepting malleable signatures, only ECDSA signatures in lower-S
* form are accepted.
*
* If you need to accept ECDSA signatures from sources that do not obey this
* rule, apply secp256k1_ecdsa_signature_normalize to the signature prior to
* validation, but be aware that doing so results in malleable signatures.
*
* For details, see the comments for that function.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify(
const secp256k1_context* ctx,
const secp256k1_ecdsa_signature *sig,
const unsigned char *msg32,
const secp256k1_pubkey *pubkey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Convert a signature to a normalized lower-S form.
*
* Returns: 1 if sigin was not normalized, 0 if it already was.
* Args: ctx: a secp256k1 context object
* Out: sigout: a pointer to a signature to fill with the normalized form,
* or copy if the input was already normalized. (can be NULL if
* you're only interested in whether the input was already
* normalized).
* In: sigin: a pointer to a signature to check/normalize (cannot be NULL,
* can be identical to sigout)
*
* With ECDSA a third-party can forge a second distinct signature of the same
* message, given a single initial signature, but without knowing the key. This
* is done by negating the S value modulo the order of the curve, 'flipping'
* the sign of the random point R which is not included in the signature.
*
* Forgery of the same message isn't universally problematic, but in systems
* where message malleability or uniqueness of signatures is important this can
* cause issues. This forgery can be blocked by all verifiers forcing signers
* to use a normalized form.
*
* The lower-S form reduces the size of signatures slightly on average when
* variable length encodings (such as DER) are used and is cheap to verify,
* making it a good choice. Security of always using lower-S is assured because
* anyone can trivially modify a signature after the fact to enforce this
* property anyway.
*
* The lower S value is always between 0x1 and
* 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0,
* inclusive.
*
* No other forms of ECDSA malleability are known and none seem likely, but
* there is no formal proof that ECDSA, even with this additional restriction,
* is free of other malleability. Commonly used serialization schemes will also
* accept various non-unique encodings, so care should be taken when this
* property is required for an application.
*
* The secp256k1_ecdsa_sign function will by default create signatures in the
* lower-S form, and secp256k1_ecdsa_verify will not accept others. In case
* signatures come from a system that cannot enforce this property,
* secp256k1_ecdsa_signature_normalize must be called before verification.
*/
SECP256K1_API int secp256k1_ecdsa_signature_normalize(
const secp256k1_context* ctx,
secp256k1_ecdsa_signature *sigout,
const secp256k1_ecdsa_signature *sigin
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3);
/** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function.
* If a data pointer is passed, it is assumed to be a pointer to 32 bytes of
* extra entropy.
*/
SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_rfc6979;
/** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */
SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_default;
/** Create an ECDSA signature.
*
* Returns: 1: signature created
* 0: the nonce generation function failed, or the private key was invalid.
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
* Out: sig: pointer to an array where the signature will be placed (cannot be NULL)
* In: msg32: the 32-byte message hash being signed (cannot be NULL)
* seckey: pointer to a 32-byte secret key (cannot be NULL)
* noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL)
*
* The created signature is always in lower-S form. See
* secp256k1_ecdsa_signature_normalize for more details.
*/
SECP256K1_API int secp256k1_ecdsa_sign(
const secp256k1_context* ctx,
secp256k1_ecdsa_signature *sig,
const unsigned char *msg32,
const unsigned char *seckey,
secp256k1_nonce_function noncefp,
const void *ndata
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Verify an ECDSA secret key.
*
* Returns: 1: secret key is valid
* 0: secret key is invalid
* Args: ctx: pointer to a context object (cannot be NULL)
* In: seckey: pointer to a 32-byte secret key (cannot be NULL)
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify(
const secp256k1_context* ctx,
const unsigned char *seckey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
/** Compute the public key for a secret key.
*
* Returns: 1: secret was valid, public key stores
* 0: secret was invalid, try again
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
* Out: pubkey: pointer to the created public key (cannot be NULL)
* In: seckey: pointer to a 32-byte private key (cannot be NULL)
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
const secp256k1_context* ctx,
secp256k1_pubkey *pubkey,
const unsigned char *seckey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Negates a private key in place.
*
* Returns: 1 always
* Args: ctx: pointer to a context object
* In/Out: seckey: pointer to the 32-byte private key to be negated (cannot be NULL)
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_negate(
const secp256k1_context* ctx,
unsigned char *seckey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
/** Negates a public key in place.
*
* Returns: 1 always
* Args: ctx: pointer to a context object
* In/Out: pubkey: pointer to the public key to be negated (cannot be NULL)
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate(
const secp256k1_context* ctx,
secp256k1_pubkey *pubkey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
/** Tweak a private key by adding tweak to it.
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
* uniformly random 32-byte arrays, or if the resulting private key
* would be invalid (only when the tweak is the complement of the
* private key). 1 otherwise.
* Args: ctx: pointer to a context object (cannot be NULL).
* In/Out: seckey: pointer to a 32-byte private key.
* In: tweak: pointer to a 32-byte tweak.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add(
const secp256k1_context* ctx,
unsigned char *seckey,
const unsigned char *tweak
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Tweak a public key by adding tweak times the generator to it.
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
* uniformly random 32-byte arrays, or if the resulting public key
* would be invalid (only when the tweak is the complement of the
* corresponding private key). 1 otherwise.
* Args: ctx: pointer to a context object initialized for validation
* (cannot be NULL).
* In/Out: pubkey: pointer to a public key object.
* In: tweak: pointer to a 32-byte tweak.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add(
const secp256k1_context* ctx,
secp256k1_pubkey *pubkey,
const unsigned char *tweak
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Tweak a private key by multiplying it by a tweak.
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
* uniformly random 32-byte arrays, or equal to zero. 1 otherwise.
* Args: ctx: pointer to a context object (cannot be NULL).
* In/Out: seckey: pointer to a 32-byte private key.
* In: tweak: pointer to a 32-byte tweak.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul(
const secp256k1_context* ctx,
unsigned char *seckey,
const unsigned char *tweak
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Tweak a public key by multiplying it by a tweak value.
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
* uniformly random 32-byte arrays, or equal to zero. 1 otherwise.
* Args: ctx: pointer to a context object initialized for validation
* (cannot be NULL).
* In/Out: pubkey: pointer to a public key obkect.
* In: tweak: pointer to a 32-byte tweak.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
const secp256k1_context* ctx,
secp256k1_pubkey *pubkey,
const unsigned char *tweak
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Updates the context randomization to protect against side-channel leakage.
* Returns: 1: randomization successfully updated
* 0: error
* Args: ctx: pointer to a context object (cannot be NULL)
* In: seed32: pointer to a 32-byte random seed (NULL resets to initial state)
*
* While secp256k1 code is written to be constant-time no matter what secret
* values are, it's possible that a future compiler may output code which isn't,
* and also that the CPU may not emit the same radio frequencies or draw the same
* amount power for all values.
*
* This function provides a seed which is combined into the blinding value: that
* blinding value is added before each multiplication (and removed afterwards) so
* that it does not affect function results, but shields against attacks which
* rely on any input-dependent behaviour.
*
* You should call this after secp256k1_context_create or
* secp256k1_context_clone, and may call this repeatedly afterwards.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize(
secp256k1_context* ctx,
const unsigned char *seed32
) SECP256K1_ARG_NONNULL(1);
/** Add a number of public keys together.
* Returns: 1: the sum of the public keys is valid.
* 0: the sum of the public keys is not valid.
* Args: ctx: pointer to a context object
* Out: out: pointer to a public key object for placing the resulting public key
* (cannot be NULL)
* In: ins: pointer to array of pointers to public keys (cannot be NULL)
* n: the number of public keys to add together (must be at least 1)
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine(
const secp256k1_context* ctx,
secp256k1_pubkey *out,
const secp256k1_pubkey * const * ins,
size_t n
) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
#ifdef __cplusplus
}
#endif
#endif /* SECP256K1_H */

View File

@ -0,0 +1,31 @@
#ifndef SECP256K1_ECDH_H
#define SECP256K1_ECDH_H
#include "secp256k1.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Compute an EC Diffie-Hellman secret in constant time
* Returns: 1: exponentiation was successful
* 0: scalar was invalid (zero or overflow)
* Args: ctx: pointer to a context object (cannot be NULL)
* Out: result: a 32-byte array which will be populated by an ECDH
* secret computed from the point and scalar
* In: pubkey: a pointer to a secp256k1_pubkey containing an
* initialized public key
* privkey: a 32-byte scalar with which to multiply the point
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh(
const secp256k1_context* ctx,
unsigned char *result,
const secp256k1_pubkey *pubkey,
const unsigned char *privkey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
#ifdef __cplusplus
}
#endif
#endif /* SECP256K1_ECDH_H */

View File

@ -0,0 +1,110 @@
#ifndef SECP256K1_RECOVERY_H
#define SECP256K1_RECOVERY_H
#include "secp256k1.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Opaque data structured that holds a parsed ECDSA signature,
* supporting pubkey recovery.
*
* The exact representation of data inside is implementation defined and not
* guaranteed to be portable between different platforms or versions. It is
* however guaranteed to be 65 bytes in size, and can be safely copied/moved.
* If you need to convert to a format suitable for storage or transmission, use
* the secp256k1_ecdsa_signature_serialize_* and
* secp256k1_ecdsa_signature_parse_* functions.
*
* Furthermore, it is guaranteed that identical signatures (including their
* recoverability) will have identical representation, so they can be
* memcmp'ed.
*/
typedef struct {
unsigned char data[65];
} secp256k1_ecdsa_recoverable_signature;
/** Parse a compact ECDSA signature (64 bytes + recovery id).
*
* Returns: 1 when the signature could be parsed, 0 otherwise
* Args: ctx: a secp256k1 context object
* Out: sig: a pointer to a signature object
* In: input64: a pointer to a 64-byte compact signature
* recid: the recovery id (0, 1, 2 or 3)
*/
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_parse_compact(
const secp256k1_context* ctx,
secp256k1_ecdsa_recoverable_signature* sig,
const unsigned char *input64,
int recid
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Convert a recoverable signature into a normal signature.
*
* Returns: 1
* Out: sig: a pointer to a normal signature (cannot be NULL).
* In: sigin: a pointer to a recoverable signature (cannot be NULL).
*/
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_convert(
const secp256k1_context* ctx,
secp256k1_ecdsa_signature* sig,
const secp256k1_ecdsa_recoverable_signature* sigin
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Serialize an ECDSA signature in compact format (64 bytes + recovery id).
*
* Returns: 1
* Args: ctx: a secp256k1 context object
* Out: output64: a pointer to a 64-byte array of the compact signature (cannot be NULL)
* recid: a pointer to an integer to hold the recovery id (can be NULL).
* In: sig: a pointer to an initialized signature object (cannot be NULL)
*/
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact(
const secp256k1_context* ctx,
unsigned char *output64,
int *recid,
const secp256k1_ecdsa_recoverable_signature* sig
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Create a recoverable ECDSA signature.
*
* Returns: 1: signature created
* 0: the nonce generation function failed, or the private key was invalid.
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
* Out: sig: pointer to an array where the signature will be placed (cannot be NULL)
* In: msg32: the 32-byte message hash being signed (cannot be NULL)
* seckey: pointer to a 32-byte secret key (cannot be NULL)
* noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL)
*/
SECP256K1_API int secp256k1_ecdsa_sign_recoverable(
const secp256k1_context* ctx,
secp256k1_ecdsa_recoverable_signature *sig,
const unsigned char *msg32,
const unsigned char *seckey,
secp256k1_nonce_function noncefp,
const void *ndata
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Recover an ECDSA public key from a signature.
*
* Returns: 1: public key successfully recovered (which guarantees a correct signature).
* 0: otherwise.
* Args: ctx: pointer to a context object, initialized for verification (cannot be NULL)
* Out: pubkey: pointer to the recovered public key (cannot be NULL)
* In: sig: pointer to initialized signature that supports pubkey recovery (cannot be NULL)
* msg32: the 32-byte message hash assumed to be signed (cannot be NULL)
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover(
const secp256k1_context* ctx,
secp256k1_pubkey *pubkey,
const secp256k1_ecdsa_recoverable_signature *sig,
const unsigned char *msg32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
#ifdef __cplusplus
}
#endif
#endif /* SECP256K1_RECOVERY_H */

10
deps/PublicChainSDK/include/util.h vendored Normal file
View File

@ -0,0 +1,10 @@
#ifndef UTIL_H
#define UTIL_H
char* teex_new_uuid();
char* bytes32_from_uuid(char* uuid);
char* uuid_from_bytes32(char* bytes32);
#endif

BIN
deps/PublicChainSDK/lib/libethrpc.a vendored Normal file

Binary file not shown.

BIN
deps/PublicChainSDK/lib/libpublicchain.a vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,28 @@
enclave {
include "stdbool.h"
include "sgx_tcrypto.h"
include "sgx_quote.h"
include "teex_mutual_ra.h"
from "sgx_tsgxssl.edl" import *;
untrusted {
teex_mutual_ra_status_t teex_do_mutual_attestation(sgx_enclave_id_t eid, int socketfd, teex_mutual_ra_context_t ra_ctx, [in, string] char *ias_client_cert_file, [in, string] const char *ias_client_key_file, bool involve_ias) allow (teex_mutual_ra_get_nonce, teex_mutual_ra_create_eckey, teex_mutual_ra_proc_remote_msg1_trusted, teex_mutual_ra_get_msg2_trusted, teex_mutual_ra_proc_remote_msg2_trusted, teex_mutual_ra_get_msg3_trusted, teex_mutual_ra_proc_remote_msg3_trusted);
};
trusted {
public teex_mutual_ra_status_t teex_mutual_ra_get_nonce(teex_mutual_ra_context_t teex_mutual_ra_ctx, [out] sgx_quote_nonce_t *p_nonce);
public teex_mutual_ra_status_t teex_mutual_ra_create_eckey(teex_mutual_ra_context_t teex_mutual_ra_ctx, [out] sgx_ec256_public_t *p_public);
public teex_mutual_ra_status_t teex_mutual_ra_proc_remote_msg1_trusted(teex_mutual_ra_context_t teex_mutual_ra_ctx, [in] const teex_mutual_ra_msg1_t *p_remote_msg1);
//public void teex_mutual_ra_create_report(teex_mutual_ra_context_t teex_mutual_ra_ctx, [in] const sgx_target_info_t *p_qe_target, [out] sgx_report_t *p_report);
public teex_mutual_ra_status_t teex_mutual_ra_get_msg2_trusted(teex_mutual_ra_context_t teex_mutual_ra_ctx, [in, size=sig_rl_size] const uint8_t *sig_rl, uint32_t sig_rl_size, [out, size=msg2_len] teex_mutual_ra_msg2_t *p_msg2, uint32_t msg2_len);
public teex_mutual_ra_status_t teex_mutual_ra_proc_remote_msg2_trusted(teex_mutual_ra_context_t teex_mutual_ra_ctx, [in, size=remote_msg2_len] const teex_mutual_ra_msg2_t *p_remote_msg2, uint32_t remote_msg2_len, [in] const sgx_target_info_t *p_qe_target, [out] sgx_report_t *p_report);
public teex_mutual_ra_status_t teex_mutual_ra_get_msg3_trusted(teex_mutual_ra_context_t teex_mutual_ra_ctx, [in, size=quote_len] const sgx_quote_t *p_quote, uint32_t quote_len, [in] const sgx_report_t *p_qe_report, [out, size=msg3_len] teex_mutual_ra_msg3_t *p_msg3, uint32_t msg3_len);
//public void teex_mutual_ra_verify_remote_report(teex_mutual_ra_context_t teex_mutual_ra_ctx, [in, size=quote_size] const sgx_quote_t *p_remote_quote, uint32_t quote_size, [in, string] const char *report_body_from_ias, [in, string] const char *signature, [in, string] const char *certchain_urlencoded);
public teex_mutual_ra_status_t teex_mutual_ra_proc_remote_msg3_trusted(teex_mutual_ra_context_t teex_mutual_ra_ctx, [in, size=remote_msg3_len] const teex_mutual_ra_msg3_t *p_remote_msg3, uint32_t remote_msg3_len, [in, string] const char *report_body_from_ias, [in, string] const char *signature_base64ed, [in, string] const char *certchain_urlencoded);
};
};

54
deps/TEEX-SSL/include/teex_mutual_ra.h vendored Normal file
View File

@ -0,0 +1,54 @@
#ifndef _TEEX_RA_H_
#define _TEEX_RA_H_
#include <stdint.h>
typedef uint32_t teex_mutual_ra_context_t;
typedef enum _teex_mutual_ra_status_t {
TEEX_MUTUAL_RA_SUCCESS = 0x0000,
TEEX_MUTUAL_RA_ERROR_UNEXPECTED = 0x0001,
TEEX_MUTUAL_RA_INVALID_PARAMETER = 0x0002,
TEEX_MUTUAL_RA_INVALID_STATE = 0x0003,
TEEX_MUTUAL_RA_EID_NOT_SETTED = 0x0004,
TEEX_MUTUAL_RA_INVALID_MESSAGE = 0x1001,
TEEX_MUTUAL_RA_MAC_VERIFY_ERROR = 0x1002,
TEEX_MUTUAL_RA_REPORT_VERIFY_ERROR = 0x1003,
TEEX_MUTUAL_RA_USER_VERIFY_ERROR = 0x1004
} teex_mutual_ra_status_t;
typedef enum _mutual_attestation_status_t {
Mutual_Attestation_NotTrusted = 0,
Mutual_Attestation_Trusted = 1
} mutual_attestation_status_t;
typedef struct _teex_mutual_ra_msg1_t {
uint32_t extended_epid_group_id; // 4 bytes
sgx_epid_group_id_t gid; // 4 bytes
sgx_ec256_public_t g_a; // 64 bytes
} teex_mutual_ra_msg1_t;
typedef struct _teex_mutual_ra_msg2_t {
sgx_mac_t mac; // 16 bytes
sgx_spid_t spid; // 16 bytes
uint32_t quote_type; // 4 bytes
uint32_t sig_rl_size; // 4 bytes
uint8_t sig_rl[];
} teex_mutual_ra_msg2_t;
typedef struct _teex_mutual_ra_msg3_t {
sgx_mac_t mac; // 16 bytes
sgx_quote_t quote;
} teex_mutual_ra_msg3_t;
typedef struct _teex_mutual_ra_msg4_t {
sgx_mac_t mac; // 16 bytes
mutual_attestation_status_t status; // 4 bytes
// sgx_platform_info_t platformInfoBlob; // 101 bytes
} teex_mutual_ra_msg4_t;
// TODO teex_mutual_ra_msg4_t
#endif

32
deps/TEEX-SSL/include/teex_ssl.edl vendored Normal file
View File

@ -0,0 +1,32 @@
enclave {
include "sgx_tkey_exchange.h"
from "sgx_tkey_exchange.edl" import *;
include "teex_mutual_ra.h"
from "teex_mutual_ra.edl" import *;
untrusted {
int teex_ssl_ocall_read(int fd, [out, size=n] void *buf, size_t n);
int teex_ssl_ocall_write(int fd, [in, size=n] const void *buf, size_t n);
void teex_ssl_ocall_print_string([in, string] const char *str);
int teex_ssl_ocall_read_file([in, string] const char *file_name, [out, size=buf_size] void *buf, int buf_size);
int teex_ssl_ocall_open_clientfd([in, string] const char *host, int port);
int teex_ssl_ocall_open_listenfd(int port);
int teex_ssl_ocall_closefd(int fd);
int do_single_attestation_responder(sgx_enclave_id_t eid, int socketfd, sgx_ra_context_t ra_ctx) allow (sgx_ra_get_ga, sgx_ra_proc_msg2_trusted, sgx_ra_get_msg3_trusted);
void *ias_agent_new();
void ias_agent_free([user_check] void *ias);
void ias_agent_initialize([user_check] void *ias, [in, string] const char *base, [in, string] const char *client_cert_file, [in, string] const char *client_key_file);
void ias_agent_destroy([user_check] void *ias);
int ias_agent_request([user_check] void *ias, [in, string] const char *url, [in, string] const char *method, [in, size=postdata_len] const void *postdata, int postdata_len, [out, size=resdata_buffer_size] void *resdata, int resdata_buffer_size, [out] int *resdata_len);
};
trusted {
};
};

71
deps/TEEX-SSL/include/teex_ssl.h vendored Normal file
View File

@ -0,0 +1,71 @@
#ifndef _TEEX_SSL_H_
#define _TEEX_SSL_H_
#ifndef _cplusplus
#include <stdbool.h>
#endif
#include <sgx_eid.h>
#include <sgx_report.h>
#include <sgx_dh.h>
#define TEEX_SSL_FLAGS_INVOLVE_IAS 0x00000001
#define TEEX_SSL_FLAGS_VERIFY_TPM 0x00000002
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _TEEX_SSL TEEX_SSL;
typedef enum {
TEEX_SSL_AUTO_DETECT = 0x1000, // can only be used by TEEX_accept
TEEX_SSL_MUTUAL_RA_INITIATOR = 0x1001,
TEEX_SSL_MUTUAL_RA_RESPONDER = 0x1002,
TEEX_SSL_SINGLE_RA_INITIATOR = 0x1003,
TEEX_SSL_SINGLE_RA_RESPONDER = 0x1004,
TEEX_SSL_NO_RA_INITIATOR = 0x1005,
TEEX_SSL_NO_RA_RESPONDER = 0x1006
} TEEX_SSL_TYPE;
typedef bool (*TEEX_SSL_remote_attestation_callback)(const sgx_report_body_t *remote_enclave_report_body, const char *remote_enclave_quote_status, void *arg);
typedef bool (*TEEX_SSL_tpm_attestation_callback)(const sgx_dh_session_enclave_identity_t *daemon_enclave_identity, const void *tpm_quote, int tpm_quote_len, const void *other_info, int other_info_len, void *arg); // XXX other_info may be the tpm measurement log, or a NULL-terminated (char const* const*) array of all pcr-extended sha1 hashs. it is always NULL temporarily.
TEEX_SSL *TEEX_SSL_new(TEEX_SSL_TYPE type);
void TEEX_SSL_free(TEEX_SSL *context);
// basic settings
void TEEX_SSL_set_self_eid(TEEX_SSL *context, sgx_enclave_id_t eid);
void TEEX_SSL_set_attributes(TEEX_SSL *context, int attr);
void TEEX_SSL_set_fd(TEEX_SSL *context, int fd);
int TEEX_SSL_get_fd(TEEX_SSL *context);
// settings about involving ias
void TEEX_SSL_set_attestation_callback(TEEX_SSL *context, TEEX_SSL_remote_attestation_callback callback, void *arg);
void TEEX_SSL_set_ias_client_cert_key(TEEX_SSL *context, const char *ias_client_cert_file, const char *ias_client_key_file);
// settings about verifing tpm
void TEEX_SSL_set_tpm_attestation_daemon_host_port(TEEX_SSL *context, const char *host, int port);
//void TEEX_SSL_set_tpm_ak_cert(TEEX_SSL *context, const char *tpm_ak_cert_file);
void TEEX_SSL_set_tpm_ak_pubkey(TEEX_SSL *context, const char *tpm_ak_pem_pubkey_file); // XXX here, we use ak pem public key instead of cert temporarily
void TEEX_SSL_set_tpm_attestation_callback(TEEX_SSL *context, TEEX_SSL_tpm_attestation_callback callback, void *arg);
int TEEX_connect(TEEX_SSL *context);
int TEEX_accept(TEEX_SSL *context);
int TEEX_read(TEEX_SSL *context, void *buf, size_t count);
int TEEX_write(TEEX_SSL *context, const void *buf, size_t count);
int TEEX_readn(TEEX_SSL *context, void *buf, size_t n);
int TEEX_writen(TEEX_SSL *context, const void *buf, size_t n);
#ifdef __cplusplus
}
#endif
#endif

BIN
deps/TEEX-SSL/lib/libteex_ssl.a vendored Normal file

Binary file not shown.

BIN
deps/TEEX-SSL/lib/libteex_tssl.a vendored Normal file

Binary file not shown.

BIN
deps/TEEX-SSL/lib/libteex_ussl.a vendored Normal file

Binary file not shown.

20
include/teex/base64.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef _BASE64_H_
#define _BASE64_H_
#define B64_ENCODE_LEN(x) (((x)+2)/3*4)
#define B64_DECODE_LEN(x) (((x)+3)/4*3)
#ifdef __cplusplus
extern "C" {
#endif
int base64_encode(const void *data, int size, char *code);
int base64_decode(const char *code, void *data);
#ifdef __cplusplus
}
#endif
#endif

20
include/teex/const.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef __TEEX_CONST_H__
#define __TEEX_CONST_H__
#define PUBLIC_KEY_LEN (40)
#define PRIVATE_KEY_LEN (64)
#define ID_LEN (32)
#define CONTRACT_ADDR_LEN (40)
#define PRICE_LEN (64)
#define HASH_LEN (32)
#define DEFAULT_CHAIN_ADDR "120.132.14.182"
#define DEFAULT_CHAIN_PORT 9545
#define DEFAULT_SERVICE_CONTRACT "aeFC4E7143e8896D6aA67f5352372c7b0D233b9b"
#define DEFAULT_TOKEN_CONTRACT "B127af3CDE8ba755F42553c383Fd368BC4f8C25a"
#endif

52
include/teex/debug.h Normal file
View File

@ -0,0 +1,52 @@
#ifndef __TEEX_DEBUG_H__
#define __TEEX_DEBUG_H__
#include <unistd.h>
#include <stdio.h>
#define NONE "\e[0m"
#define BLACK "\e[0;30m"
#define L_BLACK "\e[1;30m"
#define RED "\e[0;31m"
#define L_RED "\e[1;31m"
#define GREEN "\e[0;32m"
#define L_GREEN "\e[1;32m"
#define BROWN "\e[0;33m"
#define YELLOW "\e[1;33m"
#define BLUE "\e[0;34m"
#define L_BLUE "\e[1;34m"
#define PURPLE "\e[0;35m"
#define L_PURPLE "\e[1;35m"
#define CYAN "\e[0;36m"
#define L_CYAN "\e[1;36m"
#define GRAY "\e[0;37m"
#define WHITE "\e[1;37m"
#define BOLD "\e[1m"
#define UNDERLINE "\e[4m"
#define BLINK "\e[5m"
#define REVERSE "\e[7m"
#define HIDE "\e[8m"
#define CLEAR "\e[2J"
#define CLRLINE "\r\e[K" //or "\e[1K\r"
#define TEEX_ENABLE_DEBUG 1
#ifdef TEEX_ENABLE_DEBUG
#define TEEX_DEBUG(fmt, ...) do { \
fprintf(stderr, YELLOW "DEBUG:%s+%d " NONE "==> " fmt, __FILE__, __LINE__, ##__VA_ARGS__); \
} while(0)
#else
#define TEEX_DEBUG(fmt, ...) do { \
} while(1)
#endif /* TEEX_ENABLE_DEBUG */
#define TEEX_ERROR(fmt, ...) do { \
fprintf(stderr, RED "ERROR:%s+%d " NONE "==> " fmt, __FILE__, __LINE__, ##__VA_ARGS__); \
} while(0)
#endif /* __DEBUG_H__ */

55
include/teex/error.h Normal file
View File

@ -0,0 +1,55 @@
#ifndef __TEEX_ERROR_H__
#define __TEEX_ERROR_H__
#define TEEX_MK_ERROR(x) (0x00000000|(x))
typedef enum _teex_status_t
{
TEEX_SUCCESS = TEEX_MK_ERROR(0x0000),
TEEX_ERROR_OUT_MEMORY = TEEX_MK_ERROR(0x0002),
TEEX_ERROR_NETWORK = TEEX_MK_ERROR(0x0003),
TEEX_ERROR_INTERNAL = TEEX_MK_ERROR(0x0004),
TEEX_ERROR_NULL_ARG = TEEX_MK_ERROR(0x0005),
TEEX_ERROR_INVALID_CHAINURL = TEEX_MK_ERROR(0x1001),
TEEX_ERROR_INVALID_PRIVATE_KEY = TEEX_MK_ERROR(0x1002),
TEEX_ERROR_INVALID_PUBLIC_KEY = TEEX_MK_ERROR(0x1003),
TEEX_ERROR_INVALID_CONTRACT1 = TEEX_MK_ERROR(0x1004),
TEEX_ERROR_INVALID_CONTRACT2 = TEEX_MK_ERROR(0x1005),
TEEX_ERROR_INVALID_TASKINFO = TEEX_MK_ERROR(0x1006),
TEEX_ERROR_INVALID_TASKID_BUF = TEEX_MK_ERROR(0x1007),
TEEX_ERROR_CHAIN_DISCONNECTED = TEEX_MK_ERROR(0x1008),
TEEX_ERROR_CREATE_TASK = TEEX_MK_ERROR(0x1009),
TEEX_ERROR_CONFIRM = TEEX_MK_ERROR(0x100a),
TEEX_ERROR_TIMEOUT = TEEX_MK_ERROR(0x100b),
TEEX_ERROR_INVALID_DSPT_ADDR = TEEX_MK_ERROR(0x2001),
TEEX_ERROR_INVALID_RESULT_BUF = TEEX_MK_ERROR(0x2002),
TEEX_ERROR_INVALID_SIZE_BUF = TEEX_MK_ERROR(0x2003),
TEEX_ERROR_INVALID_WORKER_BUF = TEEX_MK_ERROR(0x2004),
TEEX_ERROR_CONNECT_DISPATCHER = TEEX_MK_ERROR(0x2005),
TEEX_ERROR_INVALID_CLIENT_CERT = TEEX_MK_ERROR(0x2006),
TEEX_ERROR_ATTESTATION_FAILED = TEEX_MK_ERROR(0x2007),
TEEX_ERROR_INVALID_JSON = TEEX_MK_ERROR(0x2008),
TEEX_ERROR_INVALID_RESP_FORMAT = TEEX_MK_ERROR(0x2009),
TEEX_ERROR_INVALID_RESULT_FORMAT = TEEX_MK_ERROR(0x200a),
TEEX_ERROR_INVALID_WORKER_ADDR = TEEX_MK_ERROR(0x200b),
TEEX_ERROR_CONNECT_WORKER = TEEX_MK_ERROR(0x200c),
TEEX_ERROR_WORKER_EXECUTION = TEEX_MK_ERROR(0x200d),
TEEX_ERROR_INVALID_FILE = TEEX_MK_ERROR(0x3001),
TEEX_ERROR_UNHANDLED_FILE_TYPE = TEEX_MK_ERROR(0x3002),
TEEX_ERROR_INVALID_SERVICEINFO = TEEX_MK_ERROR(0x4001),
TEEX_ERROR_INVALID_SERVICEID_BUF = TEEX_MK_ERROR(0x4002),
TEEX_ERROR_INVALID_MANAGER_ADDR = TEEX_MK_ERROR(0x4003),
TEEX_ERROR_CONNECT_MANAGER = TEEX_MK_ERROR(0x4004),
TEEX_ERROR_MANAGER_INTERNAL = TEEX_MK_ERROR(0x4005),
TEEX_ERROR_UNIMPLEMENTED = TEEX_MK_ERROR(0xffff),
} teex_status_t;
#endif

81
include/teex/file.h Normal file
View File

@ -0,0 +1,81 @@
#ifndef __TEEX_FILE_H__
#define __TEEX_FILE_H__
#include "teex/error.h"
#include "cjson/cJSON.h"
enum teex_file_type_t{
TEEX_DIR = 0,
TEEX_FILE,
};
typedef struct teex_file_t {
teex_file_type_t type; /* type of the file, TEEX_DIR or TEEX_FILE */
char *name; /* file name */
union {
struct {
int size; /* size of a regular file */
unsigned char *text; /* content of the file */
} file;
struct {
int fileNumber; /* number of files in a directory */
struct teex_file_t **files; /* each file in the directory */
} dir;
} body; /* file body */
} teexFile;
/* loadFile
* Purpose: Load a file/directory from the disk.
*
* Parameters:
* fileDir - [IN] the directory of the service code.
* file - [OUT] the loaded service code structure.
*
* Return value:
* teex_status_t - TEEX_SUCCESS or failure as defined in error.h
*/
teex_status_t loadFile(char *fileDir, teexFile *file);
/* calFileHash
* Purpose: calculate the SHA256 hash of the file.
*
* Parameters:
* file - [IN] the input teexFile structure.
* fileHash - [out] the SHA256 hash hexstring of the file.
*
* Return value:
* teex_status_t - TEEX_SUCCESS or failure as defined in error.h
*/
teex_status_t calFileHash(teexFile *file, char **fileHash);
/* fileToJson
* Purpose: transfer the teexFile to a JSON object
*
* Parameters:
* file - [in] the input teexFile structure.
* fileJson - [out] the output JSON object.
*
* Return value:
* teex_status_t - TEEX_SUCCESS or failure as defined in error.h
*/
teex_status_t fileToJson(teexFile *file, cJSON *fileJson);
/* jsonToFile
* Purpose: transfer the JSON object to teexFile
*
* Parameters:
* fileJson - [in] the input JSON object.
* file - [out] the output teexFile structure.
*
* Return value:
* teex_status_t - TEEX_SUCCESS or failure as defined in error.h
*/
teex_status_t jsonToFile(cJSON *fileJson, teexFile *file);
#endif

66
include/teex/service.h Normal file
View File

@ -0,0 +1,66 @@
#ifndef __TEEX_SERVICE_H__
#define __TEEX_SERVICE_H__
#include "teex/error.h"
#include "teex/file.h"
typedef struct teex_service_t {
char * serviceID; /* ID for the service */
char * price; /* price paid for the service provider */
char * workerFeerate; /* token paid for the worker */
char * desc; /* description of the service */
char * providerAddr; /* wallet address of the service provider */
char * publicKey; /* public key of the service */
char * privateKey; /* private key of the service */
teexFile *code; /* code of the service */
char * codeEntry; /* entry file of the service */
char * codeHash; /* hash of the service code */
char * runtime; /* runtime used by the service. e.g., python2.7 */
int dataNumber; /* number of data used by the service */
char **dataList; /* the data list */
} teexService;
/* createServiceOnChain
* Purpose: Create a service on the blockchain and get the serviceID.
*
* Parameters:
* chainAddr - [IN] address of the chain node.
* chainPort - [IN] port of the chain node.
* privateKey - [IN] private key of the service provider's wallet.
* publicKey - [IN] public key of the service provider's wallet.
* serviceContractAddr - [IN] the smart contract address of the TEEX service.
* tokenContractAddr - [IN] the smart contract address of the TEEX token.
* serviceInfo - [IN] the service information w/o the service ID.
* serviceID - [OUT] the service ID generated by the blockchain.
* timeout - [IN] time for confirming the created service onchain, in seconds
*
* Return value:
* teex_status_t - TEEX_SUCCESS or failure as defined in error.h
*/
teex_status_t createServiceOnChain(char *chainAddr, int chainPort,
char *privateKey, char *publicKey,
char *serviceContractAddr, char *tokenContractAddr,
teexService *serviceInfo, char **serviceID,
unsigned int timeout);
/* deployService
*
* Parameters:
* managerAddr - [IN] address of a TEEX service manager.
* managerPort - [IN] port of a TEEX service manager.
* serviceInfo - [IN] the service information.
* errMsg - [OUT] the error message from the TEEX Service Manager.
*
* Return value:
* teex_status_t - TEEX_SUCCESS or failure as defined in error.h
*/
teex_status_t deployService(char *managerAddr, int managerPort,
teexService *serviceInfo,
char **errMsg);
#endif

58
include/teex/task.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef __TEEX_INVOKE_H__
#define __TEEX_INVOKE_H__
#include "teex/error.h"
typedef struct teex_task_t {
char * taskID; /* ID for the task, generated by create_task_onchain */
char * serviceID; /* ID for the invoked service */
char * input; /* Must be a printable string */
int dataNumber; /* Number of the data used by the task */
char **dataList; /* Array of the data IDs */
char *publicKey; /* Public key of the user */
char *price; /* Price paid for the task, a printable string */
} teexTask;
/* createTaskOnChain
* Purpose: Create a task on the blockchain and get the taskID.
*
* Parameters:
* chainAddr - [IN] address of the chain node.
* chainPort - [IN] port of the chain node.
* privateKey - [IN] private key of the user wallet.
* publicKey - [IN] public key of the user wallet.
* serviceContractAddr - [IN] the smart contract address of the TEEX service.
* tokenContractAddr - [IN] the smart contract address of the TEEX token.
* task_info - [IN] the task information w/o the task ID.
* taskID - [OUT] the task ID generated by the blockchain.
* timeout - [IN] time for confirming the created task onchain, in seconds
*
* Return value:
* teex_status_t - TEEX_SUCCESS or failure as defined in error.h
*/
teex_status_t createTaskOnChain(char *chainAddr, int chainPort, char *privateKey,
char *publicKey,
char *serviceContractAddr, char *tokenContractAddr,
teexTask *taskInfo, char **taskID,
unsigned int timeout);
/* runTask
*
* Parameters:
* dispatcherURL - [IN] url of a TEEX dispatcher.
* dispatcherPort - [IN] port of a TEEX dispatcher.
* taskInfo - [IN] the task information.
* returnMsg - [OUT] the returned string of the task.
* msgLen - [OUT] the size of the returned string.
*
* Return value:
* teex_status_t - TEEX_SUCCESS or failure as defined in error.h
*/
teex_status_t runTask(char *dispatcherURL, int dispatcherPort,
teexTask *taskInfo, char **returnMsg,
int *msgLen);
#endif

16
include/teex/util.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef __TEEX_UTIL_H__
#define __TEEX_UTIL_H__
#include "teex_ssl.h"
int isNumberStr(char *str);
char* teexHexStrDup(char *str, int size);
int teexGetLine(TEEX_SSL *ts, char *buf, int size);
char *sha256AndToHexStr(char *msg, size_t mlen) ;
int teexConnect(char *addr, int port);
#endif

View File

@ -0,0 +1,2 @@
def hello_string(input):
return "String:"+input

View File

@ -0,0 +1,9 @@
from teex import *
from hello_lib import *
input_string = TEEX_getinput()
output_string = hello_string(input_string)
TEEX_return({'message': output_string})

View File

@ -0,0 +1,350 @@
# -*- coding: UTF-8 -*-
import hashlib
import json
import re
import time
import chardet
import requests
from lxml import html
from teex import *
app_key = 12574478;
jsv = '2.4.2'
def parse_html(url, cookie, params=None, is_json=False, cookie_required=False):
headers = {
'User-Agent': 'Mozilla/5.0' '(Windows' 'NT' '10.0;' 'Win64;' 'x64;' 'rv:66.0)' 'Gecko/20100101' 'Firefox/66.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Accept-Encoding': 'gzip,' 'deflate,' 'br',
'Referer': 'https://world.taobao.com/',
'Connection': 'keep-alive',
'Cookie': cookie,
'Upgrade-Insecure-Requests': '1',
'TE': 'Trailers'
}
res = requests.get(url, headers=headers, params=params)
#print(res.url)
if is_json == True:
return json.loads(re.match(".*?({.*}).*", res.text, re.S).group(1))
elif cookie_required == True:
#print(res.cookies.get_dict())
return res.cookies.get_dict(), html.fromstring(
res.content.decode('utf-8', 'ignore') if chardet.detect(res.content)[
'encoding'] == 'utf-8' else res.content)
return html.fromstring(
res.content.decode('utf-8', 'ignore') if chardet.detect(res.content)['encoding'] == 'utf-8' else res.content)
# 从cookie中解析特定key及value
def get_token(cookie, token_key):
for pair in cookie.split('; '):
key, value = pair.split('=')[:2]
if key == token_key:
#print(key, value.split('_')[0])
return value.split('_')[0]
def save_json(fname, data):
with open(fname, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=True)
# 获取_m_h5_tk及_m_h5_tk_enc cookie
def get_mh5_token(cookie):
if '_m_h5_tk' in cookie:
return cookie
url = 'https://h5api.m.taobao.com/h5/mtop.taobao.mbis.address.geconfigcity/1.0/?jsv=%s&appKey=%d&api=mtop.taobao.mbis.address.geConfigCity&v=1.0&ecode=1&needLogin=true&dataType=jsonp&type=jsonp&callback=mtopjsonp1&data={"configKey":"defaultOverseaData"}' % (
jsv, app_key)
c, _ = parse_html(url, cookie, cookie_required=True)
for key, value in c.items():
cookie = cookie + '; %s=%s' % (key, value)
return cookie
# 生成令牌
def generate_sign(token, ts, app_key, data='{}'):
value = "%s&%s&%s&%s" % (token, ts, app_key, data)
m = hashlib.md5(value.encode('utf-8'))
return m.hexdigest()
# 获取用户基本信息:真实姓名,邮箱,性别,出生日期,省市区,详细地址,电话号码,固定电话,是否将固定电话作为交易方式
# 对应网址 https://member1.taobao.com/member/fresh/account_profile.htm
def get_basic_info(cookie):
url = 'https://member1.taobao.com/member/fresh/account_profile.htm'
root = parse_html(url, cookie)
form = root.xpath('//*[@id="ah:addressForm"]/li')
basic_info = {
'name': form[0].find('strong').text,
'email': form[1].find('strong').text,
'gender': [g.get('value') for g in form[2].findall('span/input') if g.get('checked') is not None][0],
'birthday': '/'.join([b.get('value') for b in form[3].findall('input')]),
'location': '/'.join([b.get('value') for b in form[4].findall('p/select')]),
'details': form[5].find('input').get('value'),
'zipcode': form[6].find('input').get('value'),
'line_phone': form[7].find('input[@id="formatPhone"]').get('value'),
'phone_setting': False if form[8].find('span/input').get('checked') is None else True
}
#print(basic_info)
#save_json('basic_info.json', basic_info)
return basic_info
# 获取收货地址信息:收件人,所在地区,详细地址,邮编,电话/手机,是否为默认地址,是否需要升级地址(即地址是否可用)
# 对应网址 https://member1.taobao.com/member/fresh/deliver_address.htm
def get_address_info(cookie):
cookie = get_mh5_token(cookie)
url = 'http://h5api.m.taobao.com/h5/mtop.taobao.mbis.getdeliveraddrlist/1.0/'
ts = int(round(time.time() * 1000))
params = {
'jsv': jsv,
'appKey': app_key,
't': ts,
'sign': generate_sign(get_token(cookie, '_m_h5_tk'), ts, app_key),
'api': 'mtop.taobao.mbis.getDeliverAddrList',
'v': '1.0',
'ecode': 1,
'needLogin': 'true',
'dataType': 'jsonp',
'type': 'jsonp',
'callback': 'mtopjsonp4',
'data': '{}'
}
info = parse_html(url, cookie, params, is_json=True)
address_info = json.loads(info['data']['returnValue'])
info_key = ['fullName', 'fullAddress', 'addressDetail', 'post', 'mobile', 'defaultAddress', 'needUpgrade']
address_lst = [
{key: address[key] for key in info_key}
for address in address_info
]
#save_json('address_lst.json', address_lst)
return address_lst
# 获取收藏夹信息:商品图片地址,商品链接,商品名,商品是否有效,是否为天猫商品,商品所属店铺
# 对应网址 https://shoucang.taobao.com/item_collect.htm
def get_fav(cookie):
fav_start = 0
fav_lst = []
url = 'https://shoucang.taobao.com/item_collect.htm'
while True:
fav_info = None
if fav_start > 0:
url = 'https://shoucang.taobao.com/nodejs/item_collect_chunk.htm?ifAllTag=0&tab=0&tagId=&categoryCount=0&type=0&tagName=&categoryName=&needNav=false&startRow=%d&t=%d' % (
fav_start * 30, int(round(time.time() * 1000)))
root = parse_html(url, cookie)
fav_info = root.xpath('li')
else:
root = parse_html(url, cookie)
fav_info = root.xpath('//*[@id="fav-list"]/ul/li')
for f in fav_info:
fav = {
'img': f.find('div[@class="img-controller-box J_FavImgController"]/div/a/img').get('src'),
'href': f.find('div[@class="img-item-title"]/a').get('href'),
'text': f.find('div[@class="img-item-title"]/a').text,
'isvalid': not 'isinvalid' in f.get('class'),
'istmall': 'istmall' in f.get('class'),
'shop': f.find('div[@class="img-controller-box J_FavImgController"]/a[@class="go-shop-link"]').get(
'href')
}
fav_lst.append(fav)
fav_start += 1
if len(fav_info) < 30:
break
return fav_lst
#save_json('fav_lst.json', fav_lst)
# 获取购物车信息:店铺名,卖家名,[商品id商品名商品细节如鞋码选择等商品价格商品图片链接商品链接]
# 对应网址 https://cart.taobao.com/cart.htm
def get_cart(cookie):
url = 'https://cart.taobao.com/json/asyncGetMyCart.do'
params = {
'isNext': True,
'endTime': time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()),
'page': 2,
'_thwlang': 'zh_CN',
'_tb_token_': get_token(cookie, '_tb_token_'),
'_ksTS': '%d_553' % int(round(time.time() * 1000)),
'callback': 'asyncGetMyCart'
}
cart_info = parse_html(url, cookie, params, is_json=True)
#save_json('cart_info.json', cart_info)
cart_lst = [
{
'shop_name': c['title'],
'seller': c['seller'],
'items': [
[{
'id': i['id'],
'title': i['title'],
'skus': '' if 'skus' not in i.keys() else i['skus'],
'price': i['price']['now'] / 1000,
'amount': i['amount']['now'],
'img': i['pic'],
'url': i['url'],
'is_valid': i['isValid']
} for i in o['orders']
] for o in c['bundles']
]
}
for c in cart_info['list']
]
return cart_lst
#save_json('cart_lst.json', cart_lst)
# 获取已购宝贝信息支付交易id支付信息交易商品详情卖家信息店铺名店铺图片链接店铺链接店铺nick店铺id交易状态
# 对应网址 https://buyertrade.taobao.com/trade/itemlist/list_bought_items.htm
def get_buyertrade(cookie):
orders_lst = []
page_num = 1
page_size = 50
while True:
url = 'https://buyertrade.taobao.com/trade/itemlist/asyncBought.htm?action=itemlist/BoughtQueryAction&event_submit_do_query=1&_input_charset=utf8'
params = {
'pageNum': page_num,
'pageSize': page_size,
'commentStatus': 'ALL',
'prePageNo': 1
}
root = parse_html(url, cookie, params=params, is_json=True)
orders = root['mainOrders']
for o in orders:
order = {
'id': o['id'],
'pay_info': o['payInfo'],
'order_info': o['orderInfo'],
'sub_order': o['subOrders'],
'seller': {
'shop_name': o['seller']['shopName'] if 'shopName' in o['seller'].keys() else None,
'shop_img': o['seller']['shopImg'] if 'shopImg' in o['seller'].keys() else None,
'shop_url': o['seller']['shopUrl'] if 'shopUrl' in o['seller'].keys() else None,
'shop_nick': o['seller']['nick'] if 'nick' in o['seller'].keys() else None,
'shop_id': o['seller']['id'] if 'id' in o['seller'].keys() else None,
},
'status': o['statusInfo']
}
orders_lst.append(order)
if page_num >= root['page']['totalPage']:
break
else:
page_num += 1
return orders_lst
#save_json('buyertrade.json', orders_lst)
# 获取我的足迹信息day_cnt每天浏览多少my_path足迹详情
def get_footmark(cookie):
cookie = get_mh5_token(cookie)
url = 'https://h5api.m.taobao.com/h5/mtop.taobao.cmin.daycount/1.0/'
ts = int(round(time.time() * 1000))
params = {
'jsv': jsv,
'appKey': app_key,
't': ts,
'sign': generate_sign(get_token(cookie, '_m_h5_tk'), ts, app_key),
'api': 'mtop.taobao.cmin.daycount',
'v': 1.0,
'dataType': 'jsonp',
'type': 'jsonp',
'callback': 'mtopjsonp3',
'data': '{}'
}
day_cnt = parse_html(url, cookie, params=params, is_json=True)
#save_json('day_cnt.json', day_cnt)
url = 'https://h5api.m.taobao.com/h5/mtop.taobao.cmin.mypath/1.0/'
params = {
'jsv': jsv,
'appKey': app_key,
't': ts,
'sign': generate_sign(get_token(cookie, '_m_h5_tk'), ts, app_key, '{"endTime":"%d","pagSize":20}' % ts),
'api': 'mtop.taobao.cmin.mypath',
'v': 1.0,
'dataType': 'jsonp',
'type': 'jsonp',
'callback': 'mtopjsonp3',
'data': '{"endTime":"%d","pagSize":20}' % ts
}
my_path = parse_html(url, cookie, params=params, is_json=True)
#save_json('my_path.json', my_path)
return my_path
# 获取用户昵称手机及id
def get_nick_phone_id(cookie):
url = 'https://member1.taobao.com/member/fresh/account_security.htm'
root = parse_html(url, cookie)
phone_num = root.xpath('//ul[@class="account-info"]/li/span[@class="default grid-msg"]')[0].text.strip()
cookie = get_mh5_token(cookie)
ts = int(round(time.time() * 1000))
url = 'https://h5api.m.taobao.com/h5/mtop.user.getusersimple/1.0/'
params = {
'jsv': jsv,
'appKey': app_key,
't': ts,
'sign': generate_sign(get_token(cookie, '_m_h5_tk'), ts, app_key, '{}'),
'api': 'mtop.user.getUserSimple',
'v': 1.0,
'dataType': 'jsonp',
'type': 'jsonp',
'callback': 'mtopjsonp3',
'data': '{}'
}
info = parse_html(url, cookie, params=params, is_json=True)
user_info = {
'phone_num': phone_num,
'id': info['data']['userNumId'],
'nick': info['data']['nick']
}
return user_info
#save_json('nick_phone_id.json', user_info)
def getTaobaoData(cookie):
result = {}
try:
result['basicinfo'] = get_basic_info(cookie)
except Exception as e:
print('taobao basicinfo error', e)
try:
result['address'] = get_address_info(cookie)
except Exception as e:
print('taobao address error', e)
try:
result['fav'] = get_fav(cookie)
except Exception as e:
print('taobao fav error', e)
try:
result['cart'] = get_cart(cookie)
except Exception as e:
print('taobao cart error', e)
try:
result['footmark'] = get_footmark(cookie)
except Exception as e:
print('taobao footmark error', e)
try:
result['nickphoneid'] = get_nick_phone_id(cookie)
except Exception as e:
print('taobao nickphoneid error', e)
try:
result['buyertrade'] = get_buyertrade(cookie)
except Exception as e:
print('taobao buytrade error', e)
return json.dumps(result, sort_keys=True, indent=4, separators=(',', ':'),ensure_ascii=False)
if __name__ == "__main__":
cookie = TEEX_getinput()
taobao_info = getTaobaoData(cookie)
TEEX_return(taobao_info)

121
src/base64.cpp Normal file
View File

@ -0,0 +1,121 @@
#include "teex/base64.h"
static const char *base64Table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
static const unsigned char base64Map[256] = {
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 0x00-0x0F
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 0x10-0x1F
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, // 0x20-0x2F
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 64, 255, 255, // 0x30-0x3F
255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 0x40-0x4F
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, // 0x50-0x5F
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 0x60-0x6F
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255, // 0x70-0x7F
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 0x80-0x8F
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 0x90-0x9F
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 0xA0-0xAF
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 0xB0-0xBF
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 0xC0-0xCF
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 0xD0-0xDF
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 0xE0-0xEF
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 // 0xF0-0xFF
};
int base64_encode(const void *data, int size, char *code) {
int nDiv = size / 3;
int nMod = size % 3;
int i;
const unsigned char *d = (const unsigned char *)data;
unsigned int d0, d1, d2, dd;
char *p = code;
for(i = 0; i < nDiv; i++) {
d0 = *(d++);
d1 = *(d++);
d2 = *(d++);
dd = (d0<<16)|(d1<<8)|(d2);
*(p++) = base64Table[(dd>>18) & 0x3F];
*(p++) = base64Table[(dd>>12) & 0x3F];
*(p++) = base64Table[(dd>>6) & 0x3F];
*(p++) = base64Table[dd & 0x3F];
}
if(nMod == 2) {
unsigned char d0 = *(d++);
unsigned char d1 = *d;
unsigned char d2 = 0;
*(p++) = base64Table[(d0>>2) & 0x3F];
*(p++) = base64Table[((d0<<4)|(d1>>4)) & 0x3F];
*(p++) = base64Table[((d1<<2)|(d2>>6)) & 0x3F];
*(p++) = '=';
}
else if(nMod == 1) {
unsigned char d0 = *d;
unsigned char d1 = 0;
//unsigned char d2 = 0;
*(p++) = base64Table[(d0>>2) & 0x3F];
*(p++) = base64Table[((d0<<4)|(d1>>4)) & 0x3F];
*(p++) = '=';
*(p++) = '=';
}
*p = '\0';
return p - (char *)code;
}
int base64_decode(const char *code, void *data) {
int len = 0;
const char *c = code;
while(*(c++) != '\0') {
len++;
}
if(len % 4 != 0) {
return -1;
}
if(len == 0) {
return 0;
}
c = code;
int nDiv = len / 4;
unsigned int c0, c1, c2, c3, cc;
unsigned char *p = (unsigned char *)data;
int i;
for(i = 0; i+1 < nDiv; ++i) {
c0 = base64Map[(int)*(c++)];
c1 = base64Map[(int)*(c++)];
c2 = base64Map[(int)*(c++)];
c3 = base64Map[(int)*(c++)];
if(c0>=64 || c1>=64 || c2>=64 || c3>=64) {
return -1;
}
cc = (c0<<18)|(c1<<12)|(c2<<6)|(c3);
*(p++) = (cc>>16) & 0xFF;
*(p++) = (cc>>8) & 0xFF;
*(p++) = (cc) & 0xFF;
}
c0 = base64Map[(int)*(c++)];
c1 = base64Map[(int)*(c++)];
c2 = base64Map[(int)*(c++)];
c3 = base64Map[(int)*(c++)];
if(c0>=64 || c1>=64 || c2>64 || c3>64) {
return -1;
}
cc = (c0<<18)|(c1<<12);
*(p++) = (cc>>16) & 0xFF;
if(c2<=63) {
cc |= (c2<<6);
*(p++) = (cc>>8) & 0xFF;
if(c3 != 64) {
cc |= (c3);
*(p++) = (cc) & 0xFF;
}
else {
if((c2 & 0x03) != 0) {
return -1;
}
}
}
else {
if(c3 != 64 || (c1 & 0x0F) != 0) {
return -1;
}
}
return p - (unsigned char *)data;
}

315
src/file.cpp Normal file
View File

@ -0,0 +1,315 @@
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include "teex/util.h"
#include "teex/error.h"
#include "teex/file.h"
#include "teex/debug.h"
#include "teex/base64.h"
teex_status_t fileToBuf(teexFile *file, char **buf, int *size)
{
int i = 0;
teex_status_t retval = TEEX_ERROR_UNIMPLEMENTED;
if (file == NULL || buf == NULL || size == NULL)
return TEEX_ERROR_NULL_ARG;
if (file->type == TEEX_DIR) {
for (i = 0; i < file->body.dir.fileNumber; i++) {
if ((retval = fileToBuf(file->body.dir.files[i], buf, size)) != TEEX_SUCCESS)
return retval;
}
} else if (file->type == TEEX_FILE) {
*buf = (char*)realloc(*buf, *size + file->body.file.size);
memcpy(*buf + *size, file->body.file.text, file->body.file.size);
*size += file->body.file.size;
} else {
return TEEX_ERROR_INTERNAL;
}
return TEEX_SUCCESS;
}
teex_status_t calFileHash(teexFile *file, char **fileHash)
{
if (file == NULL || fileHash == NULL)
return TEEX_ERROR_NULL_ARG;
char *fileBuf = NULL;
int size = 0;
teex_status_t retval = TEEX_ERROR_UNIMPLEMENTED;
if ((retval = fileToBuf(file, &fileBuf, &size)) != TEEX_SUCCESS) {
return retval;
}
*fileHash = sha256AndToHexStr(fileBuf, size);
return TEEX_SUCCESS;
}
teex_status_t fileToJson(teexFile *file, cJSON *fileJson)
{
int i = 0;
teex_status_t retval = TEEX_ERROR_UNIMPLEMENTED;
char *bodyBase64 = NULL;
cJSON *fileArray = NULL, *fileArrayItem = NULL;
if (file == NULL || fileJson == NULL) {
return TEEX_ERROR_NULL_ARG;
}
if (file->type == TEEX_DIR) {
/* handle the dir */
cJSON_AddStringToObject(fileJson, "name", file->name);
cJSON_AddStringToObject(fileJson, "type", "DIR");
if ((fileArray = cJSON_CreateArray()) == NULL) {
return TEEX_ERROR_OUT_MEMORY;
}
for (i = 0; i < file->body.dir.fileNumber; i++) {
if ((fileArrayItem = cJSON_CreateObject()) == NULL) {
return TEEX_ERROR_OUT_MEMORY;
}
if ((retval = fileToJson(file->body.dir.files[i], fileArrayItem)) != TEEX_SUCCESS)
return retval;
cJSON_AddItemToArray(fileArray, fileArrayItem);
}
cJSON_AddItemToObject(fileJson, "files", fileArray);
return TEEX_SUCCESS;
} else if (file->type == TEEX_FILE) {
cJSON_AddStringToObject(fileJson, "name", file->name);
cJSON_AddStringToObject(fileJson, "type", "FILE");
bodyBase64 = (char*)malloc(B64_ENCODE_LEN(file->body.file.size) + 1);
memset(bodyBase64, 0, B64_ENCODE_LEN(file->body.file.size) + 1);
base64_encode(file->body.file.text, file->body.file.size, bodyBase64);
cJSON_AddStringToObject(fileJson, "code", bodyBase64);
return TEEX_SUCCESS;
} else {
printf("Never print\n");
return TEEX_ERROR_INTERNAL;
}
}
teex_status_t jsonToFile(cJSON *fileJson, teexFile *file)
{
int i = 0;
teex_status_t retval = TEEX_ERROR_UNIMPLEMENTED;
cJSON *item = NULL, *array = NULL, *arrayItem = NULL;
teexFile *fileEntry = NULL;
if ((item = cJSON_GetObjectItem(fileJson, "type")) != NULL
&& cJSON_IsString(item)) {
/* a legal files_json format*/
if (strcmp(item->valuestring, "DIR") == 0) {
/* parse dir from json */
file->type = TEEX_DIR;
if ((item = cJSON_GetObjectItem(fileJson, "name")) != NULL
&& cJSON_IsString(item) && item->valuestring) {
if ((file->name = strdup(item->valuestring)) == NULL)
return TEEX_ERROR_OUT_MEMORY;
} else {
TEEX_ERROR("Ilegal FileJson w/o 'name': %s\n", cJSON_Print(fileJson));
return TEEX_ERROR_INVALID_JSON;
}
if ((array = cJSON_GetObjectItem(fileJson, "files")) != NULL) {
file->body.dir.fileNumber = cJSON_GetArraySize(array);
file->body.dir.files = (teexFile**)malloc(sizeof(teexFile*) * file->body.dir.fileNumber);
if (file->body.dir.files == NULL)
return TEEX_ERROR_OUT_MEMORY;
memset(file->body.dir.files, 0, sizeof(teexFile*) * file->body.dir.fileNumber);
for (i = 0; i < file->body.dir.fileNumber; i++) {
if ((arrayItem = cJSON_GetArrayItem(array, i)) == NULL) {
TEEX_ERROR("Ilegal FileJson w/o %dth item: %s\n", i,
cJSON_Print(fileJson));
return TEEX_ERROR_INVALID_JSON;
}
if ((fileEntry = (teexFile*)malloc(sizeof(teexFile))) == NULL)
return TEEX_ERROR_OUT_MEMORY;
memset(fileEntry, 0, sizeof(teexFile));
if ((retval = jsonToFile(arrayItem, fileEntry)) != TEEX_SUCCESS)
return retval;
file->body.dir.files[i] = fileEntry;
}
} else {
TEEX_ERROR("Ilegal FileJson w/o 'files': %s\n", cJSON_Print(fileJson));
return TEEX_ERROR_INVALID_JSON;
}
return TEEX_SUCCESS;
} else if (strcmp(item->valuestring, "FILE") == 0) {
/* parse file from json */
file->type = TEEX_FILE;
if ((item = cJSON_GetObjectItem(fileJson, "name")) != NULL
&& cJSON_IsString(item) && item->valuestring) {
if ((file->name = strdup(item->valuestring)) == NULL)
return TEEX_ERROR_OUT_MEMORY;
} else {
TEEX_ERROR("Ilegal FileJson w/o 'name': %s\n", cJSON_Print(fileJson));
return TEEX_ERROR_INVALID_JSON;
}
if ((item = cJSON_GetObjectItem(fileJson, "code")) != NULL
&& cJSON_IsString(item) && item->valuestring) {
file->body.file.size = B64_DECODE_LEN(strlen(item->valuestring));
file->body.file.text = (unsigned char*)malloc(file->body.file.size + 1);
memset(file->body.file.text, 0, file->body.file.size + 1);
i = base64_decode(item->valuestring, file->body.file.text);
file->body.file.size = i;
file->body.file.text[i] = 0;
} else {
TEEX_ERROR("Ilegal FileJson w/o 'code': %s\n", cJSON_Print(fileJson));
return TEEX_ERROR_INVALID_JSON;
}
return TEEX_SUCCESS;
} else {
TEEX_ERROR("Ilegal file type %s\n", item->valuestring);
return TEEX_ERROR_INTERNAL;
}
} else {
TEEX_ERROR("Cannot get 'type' from json_str: %s\n", cJSON_Print(fileJson));
return TEEX_ERROR_INVALID_JSON;
}
return TEEX_SUCCESS;
}
teex_status_t loadFile(char *fileName, teexFile *file)
{
DIR *dir = NULL;
FILE *fd = NULL;
struct stat sb;
struct dirent *entry = NULL;
int n = 0;
char newName[1024];
teexFile *fileEntry = NULL;
teex_status_t retval = TEEX_ERROR_UNIMPLEMENTED;
if (fileName == NULL || file == NULL)
return TEEX_ERROR_NULL_ARG;
if (stat(fileName, &sb) >= 0 && S_ISDIR(sb.st_mode)) {
file->type = TEEX_DIR;
if ((file->name = strdup(fileName)) == NULL)
return TEEX_ERROR_OUT_MEMORY;
file->body.dir.fileNumber = 0;
file->body.dir.files = NULL;
if ((dir = opendir(fileName)) == NULL) {
return TEEX_ERROR_INVALID_FILE;
}
while ((entry = readdir(dir)) != NULL) {
/* skip the '.' and '..' directories */
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
memset(newName, 0, 1024);
sprintf(newName, "%s/%s", fileName, entry->d_name);
if ((fileEntry = (teexFile*)malloc(sizeof(teexFile))) == NULL)
return TEEX_ERROR_OUT_MEMORY;
memset(fileEntry, 0, sizeof(teexFile));
retval = loadFile(newName, fileEntry);
if (retval == TEEX_ERROR_UNHANDLED_FILE_TYPE)
continue;
if (retval != TEEX_SUCCESS) {
free(fileEntry);
return retval;
}
file->body.dir.fileNumber ++;
file->body.dir.files = (teexFile**)realloc(file->body.dir.files,
sizeof(teexFile*)*file->body.dir.fileNumber);
file->body.dir.files[file->body.dir.fileNumber - 1] = fileEntry;
}
} else if (S_ISREG(sb.st_mode)) {
file->type = TEEX_FILE;
if ((file->name = strdup(fileName)) == NULL)
return TEEX_ERROR_OUT_MEMORY;
if ((fd = fopen(fileName, "r")) == NULL)
return TEEX_ERROR_INVALID_FILE;
file->body.file.size = sb.st_size;
file->body.file.text = (unsigned char*)malloc(file->body.file.size + 1);
memset(file->body.file.text, 0, file->body.file.size + 1);
if ((n = fread(file->body.file.text, 1, file->body.file.size, fd)) <= 0) {
free(file->body.file.text);
return TEEX_ERROR_INVALID_FILE;
}
file->body.file.size = n;
return TEEX_SUCCESS;
} else {
/* other file types are not handled */
return TEEX_ERROR_UNHANDLED_FILE_TYPE;
}
}

BIN
src/invoke.o Normal file

Binary file not shown.

409
src/service.cpp Normal file
View File

@ -0,0 +1,409 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <openssl/sha.h>
#include <pwd.h>
#include "PublicChain.h"
#include "cjson/cJSON.h"
#include "teex/base64.h"
#include "teex/util.h"
#include "teex/error.h"
#include "teex/const.h"
#include "teex/service.h"
#include "teex/debug.h"
int checkServiceInfo(teexService *serviceInfo)
{
int i = 0;
if (serviceInfo == NULL)
return -1;
if (!isNumberStr(serviceInfo->price))
return -1;
if (!isNumberStr(serviceInfo->workerFeerate))
return -1;
if (serviceInfo->desc == NULL)
return -1;
if (!isNumberStr(serviceInfo->providerAddr)
|| strlen(serviceInfo->providerAddr)!=PUBLIC_KEY_LEN)
return -1;
if (!isNumberStr(serviceInfo->publicKey) || strlen(serviceInfo->publicKey) != PUBLIC_KEY_LEN)
return -1;
if (!isNumberStr(serviceInfo->privateKey) ||
strlen(serviceInfo->privateKey) != PRIVATE_KEY_LEN)
return -1;
if (serviceInfo->code == NULL)
return -1;
if (serviceInfo->codeEntry == NULL)
return -1;
if (serviceInfo->codeHash == NULL)
return -1;
if (serviceInfo->runtime == NULL)
return -1;
for (i = 0; i < serviceInfo->dataNumber; i++) {
if (!isNumberStr(serviceInfo->dataList[i]) || strlen(serviceInfo->dataList[i]) != ID_LEN)
return -1;
}
return 0;
}
teex_status_t createServiceOnChain(char *chainAddr, int chainPort,
char *privateKey, char *publicKey,
char *serviceContractAddr, char *tokenContractAddr,
teexService *serviceInfo, char **serviceID,
unsigned int timeout)
{
if (chainAddr == NULL)
return TEEX_ERROR_INVALID_CHAINURL;
if (privateKey == NULL)
return TEEX_ERROR_INVALID_PRIVATE_KEY;
if (publicKey == NULL)
return TEEX_ERROR_INVALID_PUBLIC_KEY;
if (serviceContractAddr == NULL)
return TEEX_ERROR_INVALID_CONTRACT1;
if (tokenContractAddr == NULL)
return TEEX_ERROR_INVALID_CONTRACT2;
if (serviceInfo == NULL)
return TEEX_ERROR_INVALID_SERVICEINFO;
if (serviceID == NULL)
return TEEX_ERROR_INVALID_SERVICEID_BUF;
Service service, service_res;
char chainURL[1024];
int ret = 0;
memset(chainURL, 0, 1024);
sprintf(chainURL, "http://%s:%d", chainAddr, chainPort);
PublicChain pc = PublicChain(chainURL, serviceContractAddr, tokenContractAddr,
privateKey, publicKey);
if (pc.status != 0)
return TEEX_ERROR_CHAIN_DISCONNECTED;
if (checkServiceInfo(serviceInfo) < 0)
return TEEX_ERROR_INVALID_SERVICEINFO;
strncpy(service.sp_addr, serviceInfo->providerAddr, PUBLIC_KEY_LEN);
strncpy(service.service_pk, serviceInfo->publicKey, PUBLIC_KEY_LEN);
memset(service.price, '0', PRICE_LEN);
strncpy(service.price + PRICE_LEN - strlen(serviceInfo->price),
serviceInfo->price, strlen(serviceInfo->price));
memset(service.worker_feerate, '0', PRICE_LEN);
strncpy(service.worker_feerate + PRICE_LEN - strlen(serviceInfo->workerFeerate),
serviceInfo->workerFeerate, strlen(serviceInfo->workerFeerate));
service.desc = serviceInfo->desc;
service.codeHash = serviceInfo->codeHash;
service.data_num = serviceInfo->dataNumber;
service.bound_data_list = serviceInfo->dataList;
if (pc.newService(&service) != 0) {
return TEEX_ERROR_CREATE_TASK;
}
while(timeout > 0 && ((ret = pc.getServiceByID(service.servideID, service_res)) != 0)) {
timeout --;
sleep(1);
}
if (ret != 0)
return TEEX_ERROR_TIMEOUT;
*serviceID = strdup(service.servideID);
return TEEX_SUCCESS;
}
teex_status_t generateMsgToManager(teexService *serviceInfo, char **msgToManager)
{
teex_status_t retval = TEEX_ERROR_UNIMPLEMENTED;
cJSON *serviceJson = NULL, *item = NULL;
cJSON *array= NULL, *arrayItem = NULL;
char priceBuf[PRICE_LEN + 1], workerFeerateBuf[PRICE_LEN + 1];
char *msgBody = NULL, *msgBuf = NULL;
int i = 0;
if (serviceInfo == NULL || msgToManager == NULL)
return TEEX_ERROR_INTERNAL;
if ((serviceJson = cJSON_CreateObject()) == NULL) {
return TEEX_ERROR_OUT_MEMORY;
}
cJSON_AddStringToObject(serviceJson, "service_id", serviceInfo->serviceID);
cJSON_AddStringToObject(serviceJson, "address", serviceInfo->providerAddr);
cJSON_AddStringToObject(serviceJson, "pub_key", serviceInfo->publicKey);
cJSON_AddStringToObject(serviceJson, "prv_key", serviceInfo->privateKey);
cJSON_AddStringToObject(serviceJson, "desc", serviceInfo->desc);
memset(priceBuf, 0, PRICE_LEN + 1);
memset(priceBuf, '0', PRICE_LEN);
strncpy(priceBuf + PRICE_LEN - strlen(serviceInfo->price),
serviceInfo->price, strlen(serviceInfo->price));
cJSON_AddStringToObject(serviceJson, "price", priceBuf);
memset(workerFeerateBuf, 0, PRICE_LEN + 1);
memset(workerFeerateBuf, '0', PRICE_LEN);
strncpy(workerFeerateBuf + PRICE_LEN - strlen(serviceInfo->workerFeerate),
serviceInfo->workerFeerate, strlen(serviceInfo->workerFeerate));
cJSON_AddStringToObject(serviceJson, "worker_feerate", workerFeerateBuf);
if ((item = cJSON_CreateObject()) == NULL) {
retval = TEEX_ERROR_OUT_MEMORY;
goto out;
}
if ((retval = fileToJson(serviceInfo->code, item)) != TEEX_SUCCESS)
goto out;
cJSON_AddItemToObject(serviceJson, "service_files", item);
cJSON_AddStringToObject(serviceJson, "service_entry", serviceInfo->codeEntry);
cJSON_AddStringToObject(serviceJson, "service_runtime", serviceInfo->runtime);
if (serviceInfo->dataNumber > 0) {
if ((array = cJSON_CreateArray()) == NULL) {
retval = TEEX_ERROR_OUT_MEMORY;
goto out;
}
for (i = 0; i < serviceInfo->dataNumber; i++) {
if ((arrayItem = cJSON_CreateObject()) == NULL) {
retval = TEEX_ERROR_OUT_MEMORY;
cJSON_Delete(array);
goto out;
}
cJSON_AddStringToObject(arrayItem, "data_id", serviceInfo->dataList[i]);
cJSON_AddItemToArray(array, arrayItem);
}
cJSON_AddItemToObject(serviceJson, "data_list", array);
}
if ((msgBody = strdup(cJSON_Print(serviceJson))) == NULL) {
retval = TEEX_ERROR_OUT_MEMORY;
goto out;
}
if ((msgBuf = (char*)malloc(strlen(msgBody) + 128)) == NULL) {
retval = TEEX_ERROR_OUT_MEMORY;
goto out;
}
memset(msgBuf, 0, strlen(msgBody) + 128);
sprintf(msgBuf, "PUT\nContent-Length: %d\n", strlen(msgBody));
sprintf(msgBuf, "%s%s", msgBuf, msgBody);
*msgToManager = msgBuf;
retval = TEEX_SUCCESS;
out:
if (msgBody)
free(msgBody);
if (serviceJson)
cJSON_Delete(serviceJson);
return retval;
}
teex_status_t getMsgFromManager(TEEX_SSL *ts, char **msgFromManager)
{
if (ts == NULL || msgFromManager == NULL)
return TEEX_ERROR_INTERNAL;
char buf[1024], *msg = NULL;
int msgLen = 0;
memset(buf, 0, 1024);
if (teexGetLine(ts, buf, 1024) <= 0) {
return TEEX_ERROR_NETWORK;
}
if (sscanf(buf, "Content-Length: %d\n", &msgLen) != 1) {
return TEEX_ERROR_INVALID_RESP_FORMAT;
}
if ((msg = (char*)malloc(msgLen + 1)) == NULL)
return TEEX_ERROR_OUT_MEMORY;
memset(msg, 0, msgLen + 1);
if (TEEX_readn(ts, msg, msgLen) <= 0) {
free(msg);
return TEEX_ERROR_NETWORK;
}
*msgFromManager = msg;
return TEEX_SUCCESS;
}
teex_status_t deployService(char *managerAddr, int managerPort,
teexService *serviceInfo,
char **errMsg)
{
teex_status_t retval = TEEX_ERROR_UNIMPLEMENTED;
if (managerAddr == NULL)
return TEEX_ERROR_INVALID_MANAGER_ADDR;
if (serviceInfo == NULL)
return TEEX_ERROR_INVALID_SERVICEINFO;
int managerFD = -1, tmpFD = -1;
struct timeval timeout = {600, 0};
TEEX_SSL *ts = NULL;
char *home = NULL, *cert = NULL, *key = NULL;
char *msgToManager = NULL, *msgFromManager = NULL;
cJSON *item = NULL, *msgJson = NULL;
if ((managerFD = teexConnect(managerAddr, managerPort)) < 0) {
return TEEX_ERROR_CONNECT_MANAGER;
}
if (setsockopt(managerFD, SOL_SOCKET, SO_RCVTIMEO,
(char*)&timeout, sizeof(struct timeval)) < 0) {
retval = TEEX_ERROR_NETWORK;
goto out;
}
if ((ts = TEEX_SSL_new(TEEX_SSL_SINGLE_RA_INITIATOR)) == NULL) {
retval = TEEX_ERROR_OUT_MEMORY;
goto out;
}
TEEX_SSL_set_fd(ts, managerFD);
/* get the default client cert */
if ((home = getpwuid(getuid())->pw_dir) == NULL) {
retval = TEEX_ERROR_INVALID_CLIENT_CERT;
goto out;
}
if ((cert = (char*)malloc(strlen(home) + 128)) == NULL) {
retval = TEEX_ERROR_OUT_MEMORY;
goto out;
}
memset(cert, 0, strlen(home) + 128);
snprintf(cert, strlen(home) + 128, "%s/%s", home, ".teex/.private/client.crt");
if ((key = (char*)malloc(strlen(home) + 128)) == NULL) {
retval = TEEX_ERROR_OUT_MEMORY;
goto out;
}
memset(key, 0, strlen(home) + 128);
snprintf(key, strlen(home) + 128, "%s/%s", home, ".teex/.private/client.key");
if ((tmpFD = open(cert, O_RDONLY)) < 0) {
retval = TEEX_ERROR_INVALID_CLIENT_CERT;
goto out;
}
close(tmpFD);
tmpFD = 0;
if ((tmpFD = open(key, O_RDONLY)) < 0) {
retval = TEEX_ERROR_INVALID_CLIENT_CERT;
goto out;
}
close(tmpFD);
tmpFD = 0;
/* setup the TEEX_SSL_connection */
TEEX_SSL_set_ias_client_cert_key(ts, cert, key);
TEEX_SSL_set_attributes(ts, 0);
if (TEEX_connect(ts) != 0) {
retval = TEEX_ERROR_ATTESTATION_FAILED;
goto out;
}
if (checkServiceInfo(serviceInfo) < 0) {
retval = TEEX_ERROR_INVALID_SERVICEINFO;
goto out;
}
if (!isNumberStr(serviceInfo->serviceID) || strlen(serviceInfo->serviceID) != ID_LEN) {
retval = TEEX_ERROR_INVALID_SERVICEINFO;
goto out;
}
if ((retval = generateMsgToManager(serviceInfo, &msgToManager)) != TEEX_SUCCESS){
goto out;
}
if (TEEX_writen(ts, msgToManager, strlen(msgToManager)) <= 0) {
retval = TEEX_ERROR_NETWORK;
goto out;
}
if ((retval = getMsgFromManager(ts, &msgFromManager)) != TEEX_SUCCESS) {
goto out;
}
/* parse the msg and get the result */
if ((msgJson = cJSON_Parse(msgFromManager)) == NULL) {
retval = TEEX_ERROR_INVALID_JSON;
goto out;
}
if ((item = cJSON_GetObjectItem(msgJson, "err_no")) != NULL
&& cJSON_IsNumber(item)) {
if (item->valueint == 0) {
retval = TEEX_SUCCESS;
goto out;
} else {
if ((item = cJSON_GetObjectItem(msgJson, "err_msg")) != NULL
&& cJSON_IsString(item)) {
*errMsg = strdup(item->valuestring);
retval = TEEX_ERROR_MANAGER_INTERNAL;
goto out;
} else {
retval = TEEX_ERROR_INVALID_JSON;
goto out;
}
}
} else {
retval = TEEX_ERROR_INVALID_JSON;
goto out;
}
out:
if (key)
free(key);
if (cert)
free(cert);
if (msgToManager)
free(msgToManager);
if (msgFromManager)
free(msgFromManager);
if (ts)
TEEX_SSL_free(ts);
if (msgJson)
cJSON_Delete(msgJson);
if (managerFD)
close(managerFD);
if (tmpFD)
close(tmpFD);
return retval;
}

712
src/task.cpp Normal file
View File

@ -0,0 +1,712 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <openssl/sha.h>
#include <pwd.h>
#include "PublicChain.h"
#include "cjson/cJSON.h"
#include "teex/base64.h"
#include "teex/util.h"
#include "teex/error.h"
#include "teex/task.h"
#include "teex/const.h"
#include "teex/debug.h"
int checkTaskInfo(teexTask *taskInfo)
{
int i = 0;
if (taskInfo == NULL)
return -1;
if (!isNumberStr(taskInfo->serviceID) || strlen(taskInfo->serviceID) != ID_LEN)
return -1;
if (taskInfo->input == NULL)
return -1;
if (taskInfo->dataNumber != 0 && taskInfo->dataList == NULL)
return -1;
for (i = 0; i < taskInfo->dataNumber; i++) {
if (!isNumberStr(taskInfo->dataList[i]) || strlen(taskInfo->dataList[i]) != ID_LEN)
return -1;
}
if (!isNumberStr(taskInfo->publicKey) || strlen(taskInfo->publicKey) != PUBLIC_KEY_LEN)
return -1;
if (!isNumberStr(taskInfo->price))
return -1;
return 0;
}
teex_status_t createTaskOnChain(char *chainAddr, int chainPort, char *privateKey, char *publicKey,
char *serviceContractAddr, char *tokenContractAddr,
teexTask *taskInfo, char **taskID,
unsigned int timeout)
{
int retval = TEEX_ERROR_UNIMPLEMENTED, len = 0, r = 0;
char *hash_buf;
char chainURL[1024];
/* check all the arguments */
if (chainAddr == NULL)
return TEEX_ERROR_INVALID_CHAINURL;
if (privateKey == NULL)
return TEEX_ERROR_INVALID_PRIVATE_KEY;
if (publicKey == NULL)
return TEEX_ERROR_INVALID_PUBLIC_KEY;
if (serviceContractAddr == NULL)
return TEEX_ERROR_INVALID_CONTRACT1;
if (tokenContractAddr == NULL)
return TEEX_ERROR_INVALID_CONTRACT2;
if (taskInfo == NULL)
return TEEX_ERROR_INVALID_TASKINFO;
if (taskID == NULL)
return TEEX_ERROR_INVALID_TASKID_BUF;
memset(chainURL, 0, 1024);
sprintf(chainURL, "http://%s:%d", chainAddr, chainPort);
/* connect to the blockchain */
PublicChain pc = PublicChain(chainURL, serviceContractAddr, tokenContractAddr,
privateKey, publicKey);
Task task, task_res;
if (pc.status != 0) {
return TEEX_ERROR_CHAIN_DISCONNECTED;
}
/* check the taskInfo */
if (checkTaskInfo(taskInfo) < 0) {
return TEEX_ERROR_INVALID_TASKINFO;
}
/* create a onchain task */
task.data_num = taskInfo->dataNumber;
task.bound_data_list = taskInfo->dataList;
task.servideID = taskInfo->serviceID;
/* TODO: currently timeout is useless */
task.timeout = 10;
len = strlen(taskInfo->price);
memset(task.payment, '0', 64-len);
strncpy(task.payment+64-len, taskInfo->price, len);
strncpy(task.pk_user, taskInfo->publicKey, PUBLIC_KEY_LEN);
/* calculate the input hash */
hash_buf = sha256AndToHexStr(taskInfo->input, strlen(taskInfo->input));
if (hash_buf == NULL) {
return TEEX_ERROR_INVALID_TASKINFO;
}
memcpy(task.input_hash, hash_buf, 2*HASH_LEN);
/* Send the task to chain */
if ((r = pc.newTask(&task)) != 0)
return TEEX_ERROR_CREATE_TASK;
/* confirm the task onchain */
while (timeout > 0 && (r=pc.getTaskByID(task.taskID, task_res)) != 0) {
if (r != 5)
return TEEX_ERROR_CONFIRM;
sleep(1);
timeout --;
}
if (timeout <= 0 || r != 0)
return TEEX_ERROR_TIMEOUT;
/* return the taskID */
*taskID = (char*)malloc(ID_LEN+1);
if (*taskID == NULL)
return TEEX_ERROR_OUT_MEMORY;
memset(*taskID, 0, ID_LEN+1);
strncpy(*taskID, task.taskID, ID_LEN);
return TEEX_SUCCESS;
}
teex_status_t generateMsgToWorker(teexTask *taskInfo, char **msgToWorker)
{
if (taskInfo == NULL)
return TEEX_ERROR_INVALID_TASKINFO;
if (msgToWorker == NULL)
return TEEX_ERROR_INTERNAL;
teex_status_t retval = TEEX_ERROR_UNIMPLEMENTED;
cJSON *msgJson = NULL, *dataArray = NULL, *dataItem = NULL;
char *msgBody = NULL, *msg = NULL;
char *input_base64 = NULL, *price = NULL;
char *inputHash = NULL;
int i = 0;
if ((input_base64 = (char*)malloc(B64_ENCODE_LEN(strlen(taskInfo->input) + 1))) == NULL) {
retval = TEEX_ERROR_OUT_MEMORY;
goto out;
}
memset(input_base64, 0, B64_ENCODE_LEN(strlen(taskInfo->input)) + 1);
base64_encode(taskInfo->input, strlen(taskInfo->input), input_base64);
if ((inputHash = sha256AndToHexStr(taskInfo->input, strlen(taskInfo->input))) == NULL) {
retval = TEEX_ERROR_OUT_MEMORY;
goto out;
}
if ((price = (char*)malloc(65)) == NULL) {
retval = TEEX_ERROR_OUT_MEMORY;
goto out;
}
memset(price, 0, 65);
memset(price, '0', 64);
strncpy(price + 64 - strlen(taskInfo->price), taskInfo->price, strlen(taskInfo->price));
if ((msgJson = cJSON_CreateObject()) == NULL) {
retval = TEEX_ERROR_OUT_MEMORY;
goto out;
}
cJSON_AddStringToObject(msgJson, "task_id", taskInfo->taskID);
cJSON_AddStringToObject(msgJson, "service_id", taskInfo->serviceID);
cJSON_AddStringToObject(msgJson, "input", input_base64);
cJSON_AddStringToObject(msgJson, "data_hash", inputHash);
cJSON_AddStringToObject(msgJson, "pub_key", taskInfo->publicKey);
cJSON_AddStringToObject(msgJson, "price", price);
cJSON_AddStringToObject(msgJson, "type", "TEEX");
if (taskInfo->dataNumber > 0) {
if ((dataArray = cJSON_CreateArray()) == NULL) {
retval = TEEX_ERROR_OUT_MEMORY;
goto out;
}
for (i = 0; i < taskInfo->dataNumber; i++) {
if ((dataItem = cJSON_CreateObject()) == NULL) {
retval = TEEX_ERROR_OUT_MEMORY;
goto out;
}
cJSON_AddStringToObject(dataItem, "data_id", taskInfo->dataList[i]);
cJSON_AddItemToArray(dataArray, dataItem);
}
cJSON_AddItemToObject(msgJson, "data_list", dataArray);
}
msgBody = cJSON_Print(msgJson);
if ((msg = (char*)malloc(strlen(msgBody) + 128)) == NULL) {
retval = TEEX_ERROR_OUT_MEMORY;
goto out;
}
memset(msg, 0, strlen(msgBody) + 128);
sprintf(msg, "User\n");
sprintf(msg, "%sContent-Length: %d\n", msg, strlen(msgBody));
sprintf(msg, "%s%s", msg, msgBody);
*msgToWorker = msg;
retval = TEEX_SUCCESS;
out:
if (input_base64)
free(input_base64);
if (price)
free(price);
if (msgBody)
free(msgBody);
if (msgJson)
cJSON_Delete(msgJson);
return retval;
}
teex_status_t generateMsgToDispatcher(teexTask *taskInfo, char **msgToDispatcher)
{
if (taskInfo == NULL)
return TEEX_ERROR_INVALID_TASKINFO;
if (msgToDispatcher == NULL)
return TEEX_ERROR_INTERNAL;
cJSON *msgJson = NULL;
char *msgBody = NULL, *msg = NULL;
if ((msgJson = cJSON_CreateObject()) == NULL)
return TEEX_ERROR_OUT_MEMORY;
cJSON_AddStringToObject(msgJson, "task_id", taskInfo->taskID);
cJSON_AddStringToObject(msgJson, "service_id", taskInfo->serviceID);
cJSON_AddStringToObject(msgJson, "pk", taskInfo->publicKey);
cJSON_AddStringToObject(msgJson, "price", taskInfo->price);
if ((msgBody = strdup(cJSON_Print(msgJson))) == NULL) {
free(msgJson);
return TEEX_ERROR_OUT_MEMORY;
}
free(msgJson);
if ((msg = (char*)malloc(strlen(msgBody) + 128)) == NULL) {
free(msgBody);
return TEEX_ERROR_OUT_MEMORY;
}
memset(msg, 0, strlen(msgBody) + 128);
sprintf(msg, "Dispatch\n");
sprintf(msg, "%sContent-Length: %d\n", msg, strlen(msgBody));
sprintf(msg, "%s%s", msg, msgBody);
free(msgBody);
*msgToDispatcher = msg;
return TEEX_SUCCESS;
}
teex_status_t getMsgFromDispatcher(TEEX_SSL *ts, char **msgFromDispatcher)
{
if (ts == NULL || msgFromDispatcher == NULL)
return TEEX_ERROR_INTERNAL;
char buf[1024], *msg = NULL;
int msgLen = 0;
memset(buf, 0, 1024);
if (teexGetLine(ts, buf, 1024) <= 0) {
return TEEX_ERROR_NETWORK;
}
memset(buf, 0, 1024);
if (teexGetLine(ts, buf, 1024) <= 0) {
return TEEX_ERROR_NETWORK;
}
if (sscanf(buf, "Content-Length: %d", &msgLen) != 1) {
return TEEX_ERROR_INVALID_RESP_FORMAT;
}
if ((msg = (char*)malloc(msgLen + 1)) == NULL)
return TEEX_ERROR_OUT_MEMORY;
memset(msg, 0, msgLen + 1);
if (TEEX_readn(ts, msg, msgLen) <= 0) {
free(msg);
return TEEX_ERROR_NETWORK;
}
*msgFromDispatcher = msg;
return TEEX_SUCCESS;
}
teex_status_t getMsgFromWorker(TEEX_SSL *ts, char **msgFromWorker)
{
if (ts == NULL || msgFromWorker == NULL)
return TEEX_ERROR_INTERNAL;
char buf[1024], *msg = NULL;
int msgLen = 0;
if (teexGetLine(ts, buf, 1024) <= 0) {
return TEEX_ERROR_NETWORK;
}
if (sscanf(buf, "Content-Length: %d", &msgLen) != 1) {
return TEEX_ERROR_INVALID_RESULT_FORMAT;
}
if ((msg = (char*)malloc(msgLen + 1)) == NULL)
return TEEX_ERROR_OUT_MEMORY;
memset(msg, 0, msgLen + 1);
if (TEEX_readn(ts, msg, msgLen) <= 0) {
return TEEX_ERROR_NETWORK;
}
*msgFromWorker = msg;
return TEEX_SUCCESS;
}
teex_status_t getWorkerFromDispatcher(char *dispatcherAddr, int dispatcherPort,
teexTask *taskInfo, char **workerAddr, int *workerPort)
{
/* check the arguments */
if (dispatcherAddr == NULL)
return TEEX_ERROR_INVALID_DSPT_ADDR;
if (taskInfo == NULL)
return TEEX_ERROR_INVALID_TASKINFO;
if (workerAddr == NULL)
return TEEX_ERROR_INVALID_WORKER_BUF;
if (workerPort == NULL)
return TEEX_ERROR_INVALID_WORKER_BUF;
teex_status_t retval = TEEX_ERROR_UNIMPLEMENTED;
int dispatcherFD = -1, tmpFD = -1;
struct timeval timeout = {600, 0};
TEEX_SSL *ts = NULL;
char *home = NULL, *cert = NULL, *key = NULL;
char *msgToDispatcher = NULL, *msgFromDispatcher = NULL;
cJSON *item = NULL, *workerJson = NULL;
char *addr = NULL;
int port = 0;
/* connect to the dispatcher */
if ((dispatcherFD = teexConnect(dispatcherAddr, dispatcherPort)) < 0) {
return TEEX_ERROR_CONNECT_DISPATCHER;
}
if (setsockopt(dispatcherFD, SOL_SOCKET, SO_RCVTIMEO,
(char*)&timeout, sizeof(struct timeval)) < 0) {
retval = TEEX_ERROR_NETWORK;
goto out;
}
if ((ts = TEEX_SSL_new(TEEX_SSL_SINGLE_RA_INITIATOR)) == NULL) {
retval = TEEX_ERROR_OUT_MEMORY;
goto out;
}
TEEX_SSL_set_fd(ts, dispatcherFD);
/* get the default client cert */
if ((home = getpwuid(getuid())->pw_dir) == NULL) {
retval = TEEX_ERROR_INVALID_CLIENT_CERT;
goto out;
}
if ((cert = (char*)malloc(strlen(home) + 128)) == NULL) {
retval = TEEX_ERROR_OUT_MEMORY;
goto out;
}
memset(cert, 0, strlen(home)+128);
snprintf(cert, strlen(home)+128, "%s/%s", home, ".teex/.private/client.crt");
if ((key = (char*)malloc(strlen(home) + 128)) == NULL) {
retval = TEEX_ERROR_OUT_MEMORY;
goto out;
}
memset(key, 0, strlen(home)+128);
snprintf(key, strlen(home)+128, "%s/%s", home, ".teex/.private/client.key");
if ((tmpFD=open(cert, O_RDONLY)) < 0) {
retval = TEEX_ERROR_INVALID_CLIENT_CERT;
goto out;
}
close(tmpFD);
if ((tmpFD = open(key, O_RDONLY)) < 0) {
retval = TEEX_ERROR_INVALID_CLIENT_CERT;
goto out;
}
close(tmpFD);
tmpFD = 0;
/* setup the TEEX_SSL connection */
TEEX_SSL_set_ias_client_cert_key(ts, cert, key);
TEEX_SSL_set_attributes(ts, 0);
if (TEEX_connect(ts) != 0) {
retval = TEEX_ERROR_ATTESTATION_FAILED;
goto out;
}
/* send the message to the dispatcher */
if ((retval=generateMsgToDispatcher(taskInfo, &msgToDispatcher)) != TEEX_SUCCESS) {
goto out;
}
if (TEEX_writen(ts, msgToDispatcher, strlen(msgToDispatcher)) <= 0) {
retval = TEEX_ERROR_NETWORK;
goto out;
}
/* get the return message from the dispatcher */
if ((retval=getMsgFromDispatcher(ts, &msgFromDispatcher)) != TEEX_SUCCESS) {
goto out;
}
workerJson = cJSON_Parse(msgFromDispatcher);
if (workerJson == NULL) {
retval = TEEX_ERROR_INVALID_JSON;
goto out;
}
if ((item = cJSON_GetObjectItem(workerJson, "port")) != NULL
&& cJSON_IsNumber(item)) {
port = item->valueint;
} else {
retval = TEEX_ERROR_INVALID_JSON;
goto out;
}
if ((item = cJSON_GetObjectItem(workerJson, "address")) != NULL
&& cJSON_IsString(item)) {
addr = strdup(item->valuestring);
} else {
retval = TEEX_ERROR_INVALID_JSON;
goto out;
}
*workerAddr = addr;
*workerPort = port;
retval = TEEX_SUCCESS;
out:
/* free all pointers */
if (ts)
TEEX_SSL_free(ts);
if (workerJson)
cJSON_Delete(workerJson);
/* close all FDs */
if (dispatcherFD > 0)
close(dispatcherFD);
if (tmpFD > 0)
close(tmpFD);
/* free all string */
if (cert)
free(cert);
if (key)
free(key);
if (msgToDispatcher)
free(msgToDispatcher);
if (msgFromDispatcher)
free(msgFromDispatcher);
return retval;
}
teex_status_t getResultFromWorker(char *workerAddr, int workerPort,
teexTask *taskInfo, char **returnMsg,
int *msgLen)
{
teex_status_t ret = TEEX_ERROR_UNIMPLEMENTED;
/* check the arguments */
if (workerAddr == NULL)
return TEEX_ERROR_INVALID_WORKER_ADDR;
if (taskInfo == NULL)
return TEEX_ERROR_INVALID_TASKINFO;
if (returnMsg == NULL || msgLen == NULL)
return TEEX_ERROR_INVALID_RESULT_BUF;
teex_status_t retval = TEEX_ERROR_UNIMPLEMENTED;
int workerFD = -1, tmpFD = -1;
struct timeval timeout = {600, 0};
TEEX_SSL *ts = NULL;
char *home = NULL, *cert = NULL, *key = NULL;
char *msgToWorker = NULL, *msgFromWorker = NULL;
char *result = NULL;
int resultLen = 0;
cJSON *item = NULL, *msgJson = NULL;
/* connect to the dispatcher */
if ((workerFD = teexConnect(workerAddr, workerPort)) < 0) {
return TEEX_ERROR_CONNECT_WORKER;
}
if (setsockopt(workerFD, SOL_SOCKET, SO_RCVTIMEO,
(char*)&timeout, sizeof(struct timeval)) < 0) {
retval = TEEX_ERROR_NETWORK;
goto out;
}
if ((ts = TEEX_SSL_new(TEEX_SSL_SINGLE_RA_INITIATOR)) == NULL) {
retval = TEEX_ERROR_OUT_MEMORY;
goto out;
}
TEEX_SSL_set_fd(ts, workerFD);
/* get the default client cert */
if ((home = getpwuid(getuid())->pw_dir) == NULL) {
retval = TEEX_ERROR_INVALID_CLIENT_CERT;
goto out;
}
if ((cert = (char*)malloc(strlen(home) + 128)) == NULL) {
retval = TEEX_ERROR_OUT_MEMORY;
goto out;
}
memset(cert, 0, strlen(home)+128);
snprintf(cert, strlen(home)+128, "%s/%s", home, ".teex/.private/client.crt");
if ((key = (char*)malloc(strlen(home) + 128)) == NULL) {
retval = TEEX_ERROR_OUT_MEMORY;
goto out;
}
memset(key, 0, strlen(home)+128);
snprintf(key, strlen(home)+128, "%s/%s", home, ".teex/.private/client.key");
if ((tmpFD=open(cert, O_RDONLY)) < 0) {
retval = TEEX_ERROR_INVALID_CLIENT_CERT;
goto out;
}
close(tmpFD);
if ((tmpFD = open(key, O_RDONLY)) < 0) {
retval = TEEX_ERROR_INVALID_CLIENT_CERT;
goto out;
}
close(tmpFD);
tmpFD = 0;
/* setup the TEEX_SSL connection */
TEEX_SSL_set_ias_client_cert_key(ts, cert, key);
TEEX_SSL_set_attributes(ts, 0);
if (TEEX_connect(ts) != 0) {
retval = TEEX_ERROR_ATTESTATION_FAILED;
goto out;
}
if ((retval = generateMsgToWorker(taskInfo, &msgToWorker)) != TEEX_SUCCESS) {
goto out;
}
if (TEEX_writen(ts, msgToWorker, strlen(msgToWorker)) <= 0) {
retval = TEEX_ERROR_NETWORK;
goto out;
}
if ((retval = getMsgFromWorker(ts, &msgFromWorker)) != TEEX_SUCCESS) {
goto out;
}
/* parse the msg and get the result */
if ((msgJson = cJSON_Parse(msgFromWorker)) == NULL) {
retval = TEEX_ERROR_INVALID_RESULT_FORMAT;
goto out;
}
if ((item = cJSON_GetObjectItem(msgJson, "err_no")) != NULL
&& cJSON_IsNumber(item)) {
if (item->valueint == 0) {
/* execution succeed, return the result */
if ((item = cJSON_GetObjectItem(msgJson, "ret_msg")) != NULL
&& cJSON_IsString(item)) {
resultLen = B64_DECODE_LEN(strlen(item->valuestring)) + 1;
if ((result = (char*)malloc(resultLen)) == NULL) {
retval = TEEX_ERROR_OUT_MEMORY;
goto out;
}
memset(result, 0, resultLen);
resultLen = base64_decode(item->valuestring, result);
result[resultLen] = 0;
*returnMsg = result;
*msgLen = strlen(result);
retval = TEEX_SUCCESS;
goto out;
} else {
retval = TEEX_ERROR_INVALID_RESULT_FORMAT;
goto out;
}
} else {
/* execution failed, return the error message */
if ((item = cJSON_GetObjectItem(msgJson, "err_msg")) != NULL
&& cJSON_IsString(item)) {
*returnMsg = strdup(item->valuestring);
*msgLen = strlen(item->valuestring);
retval = TEEX_ERROR_WORKER_EXECUTION;
goto out;
} else {
retval = TEEX_ERROR_INVALID_RESULT_FORMAT;
goto out;
}
}
} else {
retval = TEEX_ERROR_INVALID_RESULT_FORMAT;
goto out;
}
out:
if (key)
free(key);
if (cert)
free(cert);
if (msgToWorker)
free(msgToWorker);
if (msgFromWorker)
free(msgFromWorker);
if (ts)
TEEX_SSL_free(ts);
if (msgJson)
cJSON_Delete(msgJson);
if (workerFD)
close(workerFD);
if (tmpFD)
close(tmpFD);
return retval;
}
teex_status_t runTask(char *dispatcherAddr, int dispatcherPort,
teexTask *taskInfo, char **returnMsg,
int *msgLen)
{
teex_status_t ret = TEEX_ERROR_UNIMPLEMENTED;
int workerPort = 0;
char *workerAddr;
if (dispatcherAddr == NULL)
return TEEX_ERROR_INVALID_DSPT_ADDR;
if (taskInfo == NULL)
return TEEX_ERROR_INVALID_TASKINFO;
if (returnMsg == NULL)
return TEEX_ERROR_INVALID_RESULT_BUF;
if (msgLen == NULL)
return TEEX_ERROR_INVALID_SIZE_BUF;
if ((ret = getWorkerFromDispatcher(dispatcherAddr, dispatcherPort,
taskInfo, &workerAddr, &workerPort)) != 0) {
return ret;
}
if ((ret = getResultFromWorker(workerAddr, workerPort, taskInfo, returnMsg, msgLen)) != 0) {
return ret;
}
return TEEX_SUCCESS;
}

176
src/util.cpp Normal file
View File

@ -0,0 +1,176 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "teex/util.h"
#include "openssl/ec.h"
#include <openssl/ecdsa.h>
#include "openssl/evp.h"
#include <openssl/x509.h>
#include <openssl/cmac.h>
#include <openssl/conf.h>
#include "openssl/err.h"
#include <openssl/pem.h>
#include <openssl/bn.h>
#include <openssl/x509v3.h>
int isNumberStr(char* str)
{
char c = 0, *num_str = "0123456789abcdef";
if (str == NULL)
return 0;
if (strncasecmp(str, "0x", 2) == 0) {
str += 2;
}
while (*str) {
c = tolower(*str);
if (strchr(num_str, c) == NULL) {
return 0;
}
str++;
}
return 1;
}
char* teexHexStrDup(char *str, int size)
{
char *retp = NULL;
if (str == NULL)
return NULL;
/* skip the '0x' in string */
if (strncasecmp(str, "0x", 2) == 0)
str += 2;
/* check is number string */
if (isNumberStr(str) == 0) {
return NULL;
}
if (size > 0 && strlen(str) != size)
return NULL;
return strdup(str);
}
int teexGetLine(TEEX_SSL *ts, char *buf, int size)
{
int i = 0, n;
char c = 0;
while (i < (size-1)) {
if ((n = TEEX_read(ts, &c, 1)) <= 0)
break;
if (c == '\n')
break;
buf[i] = c;
i++;
}
buf[i] = c;
return i;
}
void teexBinToHexStr(void *vsrc, size_t len, char *out) {
const char *_hextable = "0123456789abcdef";
const unsigned char *src= (const unsigned char *) vsrc;
char *bp = out;
size_t i;
for(i= 0; i < len; ++i) {
*(bp++) = _hextable[(src[i]>>4)&0xf];
*(bp++) = _hextable[src[i]&0xf];
}
*bp = '\0';
}
char *sha256AndToHexStr(char *msg, size_t mlen)
{
unsigned char hash_hex[32];
char *hash_str = (char*)malloc(65);
//EVP_MD_CTX *ctx = EVP_MD_CTX_new();
memset(hash_hex, 0, 32);
SHA256((unsigned char *)msg, mlen, hash_hex);
/* transfer hash_hex into str */
memset(hash_str, 0, 65);
teexBinToHexStr(hash_hex, 32, hash_str);
return hash_str;
}
int teexConnect(char *host, int port)
{
int r, clientfd;
struct addrinfo *addrs = NULL, *addr;
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
char port_string[20];
snprintf(port_string, 19, "%d", port);
r = getaddrinfo(host, port_string, &hints, &addrs);
if (r != 0)
return -1;
clientfd = ~0;
for (addr= addrs; addr != NULL; addr= addr->ai_next) {
clientfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (clientfd < 0)
continue;
struct sockaddr ai_addr = *(addr->ai_addr);
r = connect(clientfd, &ai_addr, (int) addr->ai_addrlen);
if (r == 0)
break;
close(clientfd);
clientfd = ~0;
}
freeaddrinfo(addrs);
if(clientfd < 0)
return -1;
return clientfd;
}

136
tests/test.cpp Normal file
View File

@ -0,0 +1,136 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "teex/task.h"
#include "teex/const.h"
#include "teex/file.h"
#include "teex/service.h"
char* create_service(char *serviceDir, char *serviceEntry)
{
teexFile *file = (teexFile*)malloc(sizeof(teexFile));
teex_status_t retval;
char *pubKey = "8F2d0Fa9995Eb0B041B48fBCbC0f92bFe6CFb8B5";
char *prvKey = "708a16c5642ec951e4c11b819d7c5f30b00fdacbf2c8109f6d707f0796544599";
/* Step-0: load the service code */
if ((retval = loadFile(serviceDir, file)) != TEEX_SUCCESS) {
printf("load file %s error %x\n", serviceDir, retval);
return NULL;
}
/* Step-1: init the service info */
teexService *serviceInfo = (teexService*)malloc(sizeof(teexService));
serviceInfo->price = "002";
serviceInfo->workerFeerate = "001";
serviceInfo->desc = "HelloWorld Demo";
serviceInfo->providerAddr = pubKey;
serviceInfo->publicKey = pubKey;
serviceInfo->privateKey = prvKey;
serviceInfo->code = file;
serviceInfo->codeEntry = serviceEntry;
/* calculate the hash of the service code */
if ((retval = calFileHash(file, &serviceInfo->codeHash)) != TEEX_SUCCESS) {
printf("cal code hash failed %x\n", retval);
return NULL;
}
serviceInfo->runtime = "python3.7";
serviceInfo->dataNumber = 0;
serviceInfo->dataList = NULL;
/* Step-2: create the service on the blockchain */
if ((retval = createServiceOnChain(DEFAULT_CHAIN_ADDR, DEFAULT_CHAIN_PORT,
prvKey, pubKey,
DEFAULT_SERVICE_CONTRACT, DEFAULT_TOKEN_CONTRACT,
serviceInfo, &serviceInfo->serviceID,
10)) != TEEX_SUCCESS) {
printf("create service onchain Error %x\n", retval);
return NULL;
}
/* Step-3: deploy the service on the HCloud and get the service ID
* user should provide the ip and port of the service manager
*/
char *errMsg = NULL;
if ((retval = deployService("127.0.0.1", 12000, serviceInfo, &errMsg)) != TEEX_SUCCESS) {
printf("deploy Service Error %x\n", retval);
return NULL;
}
/* return the service ID */
return strdup(serviceInfo->serviceID);
}
int create_task(char *serviceID)
{
teexTask Task;
/* Step-0: Init the Task Information */
Task.serviceID = strdup(serviceID);
Task.input = "thw=cn; cna=OLFOFZBoYVMCAcp4KFKCxC+z; t=525543e96ee924b2c875dddeeadefffa; hng=CN%7Czh-CN%7CCNY%7C156; tg=0; x=e%3D1%26p%3D*%26s%3D0%26c%3D0%26f%3D0%26g%3D0%26t%3D0; _fbp=fb.1.1563181673122.354682555; cookie2=1ab9503d242b5105d11a8d485761803e; _tb_token_=5e33a581349e7; v=0; _m_h5_tk=0857521e057d61757c0e7fbe44bd8c41_1563449138217; _m_h5_tk_enc=5301a04fa21ce1fe3a36e004bf64f21f; l=cB_qUzzrqxUeQXGBKOCZSuI8Lu79jIRAguPRwCYMi_5CTs81VM_OkqhXMUJ6cfWd_jTB4wpNddy9-eteiHJXJfIpXUJ1.; isg=BG9vIli2btZ81Wr_03QtCEnj_oq5vMIynA69k4H8Gl7l0I_Siea8h32CUojLqJuu; unb=687744600; uc1=cookie16=VT5L2FSpNgq6fDudInPRgavC%2BQ%3D%3D&cookie21=UtASsssmeWzt&cookie15=V32FPkk%2Fw0dUvg%3D%3D&existShop=false&pas=0&cookie14=UoTaG7u41g%2BfgA%3D%3D&tag=8&lng=zh_CN; sg=701; _l_g_=Ug%3D%3D; skt=0de1b21d8376d7e1; cookie1=W8yen59pXqphr176w4WvBnATyFgXZpq0xDOZLfM3w0w%3D; csg=63e8c5da; uc3=vt3=F8dBy3zdlkhhgg66QQU%3D&id2=VWeWQ6lYS6VW&nk2=AHnXtAK1t91wrQ%3D%3D&lg2=URm48syIIVrSKA%3D%3D; existShop=MTU2MzQzOTQzNw%3D%3D; tracknick=cca7777777; lgc=cca7777777; _cc_=UIHiLt3xSw%3D%3D; dnk=cca7777777; _nk_=cca7777777; cookie17=VWeWQ6lYS6VW; mt=ci=-1_0&np=";
/* data Number could be zero */
Task.dataNumber = 0;
Task.dataList = NULL;
Task.publicKey = "8F2d0Fa9995Eb0B041B48fBCbC0f92bFe6CFb8B5";
Task.price = "2";
char *newTaskID = NULL;
char *pubKey = "8F2d0Fa9995Eb0B041B48fBCbC0f92bFe6CFb8B5";
char *prvKey = "708a16c5642ec951e4c11b819d7c5f30b00fdacbf2c8109f6d707f0796544599";
char *buf = (char*)malloc(1024);
int r = 0;
memset(buf, 0, 1024);
sprintf(buf, "http://%s:%d", DEFAULT_CHAIN_ADDR, DEFAULT_CHAIN_PORT);
/* Step-1: create the task on the blockchain */
if ((r = createTaskOnChain(DEFAULT_CHAIN_ADDR, DEFAULT_CHAIN_PORT, prvKey, pubKey, DEFAULT_SERVICE_CONTRACT, DEFAULT_TOKEN_CONTRACT, &Task, &newTaskID, 10)) != TEEX_SUCCESS) {
printf("Create Task Error: %x\n", r);
return -1;
}
Task.taskID = newTaskID;
char *returnMsg = NULL;
int msgLen = 0;
/* Step-2: Invoke the task
* User should provide the ip and port of the disptacher
*/
if ((r = runTask("127.0.0.1", 9080, &Task, &returnMsg, &msgLen)) != TEEX_SUCCESS) {
printf("Run Task Error: %x\n", r);
if (r == TEEX_ERROR_WORKER_EXECUTION)
printf("Error Msg is %s\n", returnMsg);
return -1;
}
printf("Execution Result\n%s\n", returnMsg);
return 0;
}
int main()
{
/* the dir of the service code and the entry file of the service code */
char *serviceID = create_service("sampleService/taoBaoSpider",
"sampleService/taoBaoSpider/taobao_spider.py");
/* create and invoke the task */
if (serviceID != NULL)
create_task(serviceID);
}