diff --git a/Connector/config.json b/Connector/config.json index 6b84876c..ce85cadc 100644 --- a/Connector/config.json +++ b/Connector/config.json @@ -1,3 +1,3 @@ { - "version": "1.1.6" + "version": "1.1.8" } diff --git a/Connector/xmr/apirpc.py b/Connector/xmr/apirpc.py index 16a490cb..6e84794c 100644 --- a/Connector/xmr/apirpc.py +++ b/Connector/xmr/apirpc.py @@ -1,14 +1,263 @@ +from httputils import httputils from .constants import * -from .connector import RPC_ENDPOINT +from .connector import RPC_MONEROD_ENDPOINT, RPC_WALLET_ENDPOINT, WALLET_NAME, WALLET_PASSWORD from rpcutils import rpcutils, errorhandler as rpcerrorhandler from rpcutils.rpcconnector import RPCConnector from . import utils from logger import logger +@httputils.getMethod @rpcutils.rpcMethod -def syncing(id, params): +def getFeePerByte(id, params): + logger.printInfo(f"Executing RPC method getFeePerByte with id {id} and params {params}") + + requestSchema, responseSchema = utils.getMethodSchemas(GET_FEE_PER_BYTE) + + err = rpcutils.validateJSONRPCSchema(params, requestSchema) + if err is not None: + raise rpcerrorhandler.BadRequestError(err.message) + + fee = RPCConnector.request(RPC_MONEROD_ENDPOINT, id, GET_FEE_ESTIMATE_METHOD, None) + + if fee is None: + logger.printWarning("Could not get fee info from node") + raise rpcerrorhandler.BadRequestError("Could not get fee info from node") + + response = { + FEE_PER_BYTE: fee[FEE] + } + + err = rpcutils.validateJSONRPCSchema(response, responseSchema) + if err is not None: + raise rpcerrorhandler.BadRequestError(err.message) + + return response + + +@httputils.postMethod +@rpcutils.rpcMethod +def getBlockByNumber(id, params): + logger.printInfo(f"Executing RPC method getBlockByNumber with id {id} and params {params}") + + requestSchema, responseSchema = utils.getMethodSchemas(GET_BLOCK_BY_NUMBER) + + err = rpcutils.validateJSONRPCSchema(params, requestSchema) + if err is not None: + raise rpcerrorhandler.BadRequestError(err.message) + + try: + blockNumber = int(params[BLOCK_NUMBER], base=10) + except Exception as err: + raise rpcerrorhandler.BadRequestError(str(err)) + + block = RPCConnector.request(RPC_MONEROD_ENDPOINT, id, GET_BLOCK_METHOD, [blockNumber]) + + if block is None: + logger.printWarning("Could not get block info from node") + raise rpcerrorhandler.BadRequestError("Could not get block info from node") + + err = rpcutils.validateJSONRPCSchema(block, responseSchema) + if err is not None: + raise rpcerrorhandler.BadRequestError(err.message) + + return block + + +@httputils.postMethod +@rpcutils.rpcMethod +def getBlockByHash(id, params): + logger.printInfo(f"Executing RPC method getBlockByHash with id {id} and params {params}") + + requestSchema, responseSchema = utils.getMethodSchemas(GET_BLOCK_BY_HASH) + + err = rpcutils.validateJSONRPCSchema(params, requestSchema) + if err is not None: + raise rpcerrorhandler.BadRequestError(err.message) + + block = RPCConnector.request(RPC_MONEROD_ENDPOINT, id, GET_BLOCK_METHOD, [params[BLOCK_HASH]]) + + if block is None: + logger.printWarning("Could not get block info from node") + raise rpcerrorhandler.BadRequestError("Could not get block info from node") + + err = rpcutils.validateJSONRPCSchema(block, responseSchema) + if err is not None: + raise rpcerrorhandler.BadRequestError(err.message) + + return block + + +@httputils.getMethod +@rpcutils.rpcMethod +def getHeight(id, params): + logger.printInfo(f"Executing RPC method getHeight with id {id} and params {params}") + + requestSchema, responseSchema = utils.getMethodSchemas(GET_HEIGHT) + + err = rpcutils.validateJSONRPCSchema(params, requestSchema) + if err is not None: + raise rpcerrorhandler.BadRequestError(err.message) + + blockchainInfo = RPCConnector.request(RPC_MONEROD_ENDPOINT, id, GET_INFO_METHOD, None) + + if blockchainInfo is None: + logger.printWarning("Could not get latest blockchain info from node") + raise rpcerrorhandler.BadRequestError("Could not get latest blockchain info from node") + + response = { + LATEST_BLOCK_INDEX: blockchainInfo[HEIGHT], + LATEST_BLOCK_HASH: blockchainInfo[TOP_BLOCK_HASH] + } + + err = rpcutils.validateJSONRPCSchema(response, responseSchema) + if err is not None: + raise rpcerrorhandler.BadRequestError(err.message) + + return response + + +@httputils.postMethod +@rpcutils.rpcMethod +def getTxProof(id, params): + logger.printInfo(f"Executing RPC method getTxProof with id {id} and params {params}") + + requestSchema, responseSchema = utils.getMethodSchemas(GET_TX_PROOF) + + err = rpcutils.validateJSONRPCSchema(params, requestSchema) + if err is not None: + raise rpcerrorhandler.BadRequestError(err.message) + + logger.printInfo(f"Trying to open the wallet {WALLET_NAME}") + RPCConnector.request(RPC_WALLET_ENDPOINT, id, OPEN_WALLET_METHOD, WALLET_NAME, WALLET_PASSWORD) + + sign = RPCConnector.request(RPC_WALLET_ENDPOINT, id, GET_TX_PROOF_METHOD, [params[TX_ID], params[ADDRESS], params[MESSAGE]]) + if sign is None: + logger.printWarning(f"Could not get any signature from transaction id {params[TX_ID]}") + raise rpcerrorhandler.BadRequestError(f"Could not get any signature from transaction id {params[TX_ID]}") + + response = { + SIGNATURE: sign[SIGNATURE] + } + + err = rpcutils.validateJSONRPCSchema(response, responseSchema) + if err is not None: + raise rpcerrorhandler.BadRequestError(err.message) + + return response + + +@httputils.postMethod +@rpcutils.rpcMethod +def checkTxProof(id, params): + logger.printInfo(f"Executing RPC method checkTxProof with id {id} and params {params}") + + requestSchema, responseSchema = utils.getMethodSchemas(CHECK_TX_PROOF) + + err = rpcutils.validateJSONRPCSchema(params, requestSchema) + if err is not None: + raise rpcerrorhandler.BadRequestError(err.message) + + logger.printInfo(f"Trying to open the wallet {WALLET_NAME}") + RPCConnector.request(RPC_WALLET_ENDPOINT, id, OPEN_WALLET_METHOD, WALLET_NAME, WALLET_PASSWORD) + + txProof = RPCConnector.request(RPC_WALLET_ENDPOINT, id, CHECK_TX_PROOF_METHOD, [params[TX_ID], params[ADDRESS], params[MESSAGE], params[SIGNATURE]]) + + if txProof is None: + logger.printWarning("Could not get any transaction proof info from node") + raise rpcerrorhandler.BadRequestError("Could not get any transaction proof info from node") + + if txProof[PROVEN] == "false": + logger.printWarning(f"Transaction {txProof[TX_ID]} can't be proven") + response = { + PROVEN: False + } + + response = { + CONFIRMATIONS: txProof[CONFIRMATIONS], + PROVEN: True, + AMOUNT: txProof[RECEIVED] + } + + err = rpcutils.validateJSONRPCSchema(response, responseSchema) + if err is not None: + raise rpcerrorhandler.BadRequestError(err.message) + + return response + + +@httputils.postMethod +@rpcutils.rpcMethod +def getSpendProof(id, params): + logger.printInfo(f"Executing RPC method getSpendProof with id {id} and params {params}") + + requestSchema, responseSchema = utils.getMethodSchemas(GET_SPEND_PROOF) + + err = rpcutils.validateJSONRPCSchema(params, requestSchema) + if err is not None: + raise rpcerrorhandler.BadRequestError(err.message) + + logger.printInfo(f"Trying to open the wallet {WALLET_NAME}") + RPCConnector.request(RPC_WALLET_ENDPOINT, id, OPEN_WALLET_METHOD, WALLET_NAME, WALLET_PASSWORD) + + sign = RPCConnector.request(RPC_WALLET_ENDPOINT, id, GET_SPEND_PROOF_METHOD, [params[TX_ID], params[MESSAGE]]) + + if sign is None: + logger.printWarning(f"Could not generate any signature from transaction id {params[TX_ID]} to proof the spend") + raise rpcerrorhandler.BadRequestError(f"Could not generate any signature from transaction id {params[TX_ID]} to proof the spend") + + response = { + SIGNATURE: sign[SIGNATURE] + } + + err = rpcutils.validateJSONRPCSchema(response, responseSchema) + if err is not None: + raise rpcerrorhandler.BadRequestError(err.message) + + return response + + +@httputils.postMethod +@rpcutils.rpcMethod +def checkSpendProof(id, params): + logger.printInfo(f"Executing RPC method checkSpendProof with id {id} and params {params}") + + requestSchema, responseSchema = utils.getMethodSchemas(CHECK_SPEND_PROOF) + + err = rpcutils.validateJSONRPCSchema(params, requestSchema) + if err is not None: + raise rpcerrorhandler.BadRequestError(err.message) + + logger.printInfo(f"Trying to open the wallet {WALLET_NAME}") + RPCConnector.request(RPC_WALLET_ENDPOINT, id, OPEN_WALLET_METHOD, WALLET_NAME, WALLET_PASSWORD) + + txProof = RPCConnector.request(RPC_WALLET_ENDPOINT, id, CHECK_SPEND_PROOF_METHOD, [params[TX_ID], params[MESSAGE], params[SIGNATURE]]) + + if txProof is None: + logger.printWarning("Could not get any spend proof info from node") + raise rpcerrorhandler.BadRequestError("Could not get any spend proof info from node") + + if txProof[PROVEN] == "false": + logger.printWarning("Spent can't be proven") + response = { + PROVEN: False + } + + response = { + PROVEN: True + } + + err = rpcutils.validateJSONRPCSchema(response, responseSchema) + if err is not None: + raise rpcerrorhandler.BadRequestError(err.message) + + return response + + +@httputils.getMethod +@rpcutils.rpcMethod +def syncing(id, params): logger.printInfo(f"Executing RPC method syncing with id {id} and params {params}") requestSchema, responseSchema = utils.getMethodSchemas(SYNCING) @@ -17,14 +266,14 @@ def syncing(id, params): if err is not None: raise rpcerrorhandler.BadRequestError(err.message) - blockchainInfo = RPCConnector.request(RPC_ENDPOINT, id, GET_INFO, None) + blockchainInfo = RPCConnector.request(RPC_MONEROD_ENDPOINT, id, GET_INFO_METHOD, None) if blockchainInfo is None: logger.printWarning("Could not get blockchain info from node") raise rpcerrorhandler.BadRequestError("Could not get blockchain info from node") if not blockchainInfo[SYNCHRONIZED]: - syncInfo = RPCConnector.request(RPC_ENDPOINT, id, GET_SYNC_INFO, None) + syncInfo = RPCConnector.request(RPC_MONEROD_ENDPOINT, id, GET_SYNC_INFO_METHOD, None) if syncInfo is None: logger.printWarning("Could not get syncing info from node") @@ -35,7 +284,7 @@ def syncing(id, params): SYNC_PERCENTAGE: f'{str(syncInfo[HEIGHT] / syncInfo[TARGET_HEIGHT] * 100)}%', CURRENT_BLOCK_INDEX: str(syncInfo[HEIGHT]), - LATEST_BLOCK_INDEX: str(syncInfo[TARGET_HEIGHT]), + LATEST_BLOCK: str(syncInfo[TARGET_HEIGHT]), } else: response = {SYNCING: False} diff --git a/Connector/xmr/connector.py b/Connector/xmr/connector.py index 62385e3c..85c0602e 100644 --- a/Connector/xmr/connector.py +++ b/Connector/xmr/connector.py @@ -1,5 +1,15 @@ +#!/usr/bin/python3 +from . import utils + RPC_MONEROD_PORT = 38081 RPC_MONEROD_HOST = "monerod" + +RPC_WALLET_PORT = 38088 +RPC_WALLET_HOST = "wallet" RPC_MONEROD_ENDPOINT = "json_rpc" -RPC_ENDPOINT = "http://{}:{}/{}".format(RPC_MONEROD_HOST, RPC_MONEROD_PORT, RPC_MONEROD_ENDPOINT) +WALLET_NAME = utils.getWalletName() +WALLET_PASSWORD = "swapper" + +RPC_MONEROD_ENDPOINT = "http://{}:{}/{}".format(RPC_MONEROD_HOST, RPC_MONEROD_PORT, RPC_MONEROD_ENDPOINT) +RPC_WALLET_ENDPOINT = "http://{}:{}/{}".format(RPC_WALLET_HOST, RPC_WALLET_PORT, RPC_MONEROD_ENDPOINT) diff --git a/Connector/xmr/constants.py b/Connector/xmr/constants.py index 26c67971..f47d3a09 100644 --- a/Connector/xmr/constants.py +++ b/Connector/xmr/constants.py @@ -1,4 +1,15 @@ SYNCING = "syncing" +GET_ADDRESS_BALANCE = "getaddressbalance" +GET_ADDRESSES_BALANCE = "getaddressesbalance" +GET_BLOCK_BY_HASH = "getblockbyhash" +GET_BLOCK_BY_NUMBER = "getblockbynumber" +GET_FEE_PER_BYTE = "getfeeperbyte" +GET_HEIGHT = "getheight" +GET_TRANSACTION = "gettransaction" +CHECK_SPEND_PROOF = "checkSpendProof" +CHECK_TX_PROOF = "checkTxProof" +GET_TX_PROOF = "getTxProof" +GET_SPEND_PROOF = "getSpendProof" RPC_JSON_SCHEMA_FOLDER = "xmr/rpcschemas/" WS_JSON_SCHEMA_FOLDER = "xmr/wsschemas/" @@ -12,7 +23,35 @@ SYNCHRONIZED = "synchronized" SYNC_PERCENTAGE = "syncPercentage" CURRENT_BLOCK_INDEX = "currentBlock" -LATEST_BLOCK_INDEX = "latestBlock" +LATEST_BLOCK_INDEX = "latestBlockIndex" +LATEST_BLOCK_HASH = "latestBlockHash" +LATEST_BLOCK = "latestBlock" +FEE = "fee" +FEE_PER_BYTE = "feePerByte" +HASH = "hash" +BLOCK_HEADER = "block_header" +BLOCK_NUMBER = "blockNumber" +BLOCK_HASH = "blockHash" +TOP_BLOCK_HASH = "top_block_hash" +CONFIRMATIONS = "confirmations" +GOOD = "good" +PROVEN = "proven" +IN_POOL = "in_pool" +IN_POOL_RESPONSE = "inPool" +AMOUNT = "amount" +RECEIVED = "received" +TX_ID = "txid" +ADDRESS = "address" +MESSAGE = "message" +SIGNATURE = "signature" -GET_SYNC_INFO = "sync_info" -GET_INFO = "get_info" +GET_SYNC_INFO_METHOD = "sync_info" +GET_INFO_METHOD = "get_info" +GET_FEE_ESTIMATE_METHOD = "get_fee_estimate" +GET_BLOCK_METHOD = "get_block" +GET_LAST_BLOCK_HEADER_METHOD = "get_last_block_header" +CHECK_TX_PROOF_METHOD = "check_tx_proof" +CHECK_SPEND_PROOF_METHOD = "check_spend_proof" +OPEN_WALLET_METHOD = "open_wallet" +GET_TX_PROOF_METHOD = "get_tx_proof" +GET_SPEND_PROOF_METHOD = "get_spend_proof" diff --git a/Connector/xmr/rpcschemas/checkspendproof_request.json b/Connector/xmr/rpcschemas/checkspendproof_request.json new file mode 100644 index 00000000..da1c178f --- /dev/null +++ b/Connector/xmr/rpcschemas/checkspendproof_request.json @@ -0,0 +1,22 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "title": "", + "description": "", + "type": "object", + "properties": { + "txid" : { + "type": "string" + }, + "message": { + "type": "string" + }, + "signature": { + "type": "string" + } + }, + "required": [ + "txid", + "message", + "signature" + ] +} \ No newline at end of file diff --git a/Connector/xmr/rpcschemas/checkspendproof_response.json b/Connector/xmr/rpcschemas/checkspendproof_response.json new file mode 100644 index 00000000..797cc4f6 --- /dev/null +++ b/Connector/xmr/rpcschemas/checkspendproof_response.json @@ -0,0 +1,14 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "title": "", + "description": "", + "type": "object", + "properties": { + "proven":{ + "type": "boolean" + } + }, + "required": [ + "proven" + ] +} \ No newline at end of file diff --git a/Connector/xmr/rpcschemas/checktxproof_request.json b/Connector/xmr/rpcschemas/checktxproof_request.json new file mode 100644 index 00000000..b2ad72c5 --- /dev/null +++ b/Connector/xmr/rpcschemas/checktxproof_request.json @@ -0,0 +1,26 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "title": "", + "description": "", + "type": "object", + "properties": { + "txid" : { + "type": "string" + }, + "address": { + "type": "string" + }, + "message": { + "type": "string" + }, + "signature": { + "type": "string" + } + }, + "required": [ + "txid", + "address", + "message", + "signature" + ] +} \ No newline at end of file diff --git a/Connector/xmr/rpcschemas/checktxproof_response.json b/Connector/xmr/rpcschemas/checktxproof_response.json new file mode 100644 index 00000000..afb2e865 --- /dev/null +++ b/Connector/xmr/rpcschemas/checktxproof_response.json @@ -0,0 +1,23 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "title": "", + "description": "", + "type": "object", + "properties": { + "confirmations": { + "type": "integer" + }, + "proven":{ + "type": "boolean" + }, + "inPool":{ + "type": "boolean" + }, + "amount":{ + "type": "integer" + } + }, + "required": [ + "proven" + ] +} \ No newline at end of file diff --git a/Connector/xmr/rpcschemas/getblockbyhash_request.json b/Connector/xmr/rpcschemas/getblockbyhash_request.json new file mode 100644 index 00000000..6bdb8168 --- /dev/null +++ b/Connector/xmr/rpcschemas/getblockbyhash_request.json @@ -0,0 +1,14 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "title": "", + "description": "", + "type": "object", + "properties": { + "blockHash" : { + "type": "string" + } + }, + "required": [ + "blockHash" + ] +} \ No newline at end of file diff --git a/Connector/xmr/rpcschemas/getblockbyhash_response.json b/Connector/xmr/rpcschemas/getblockbyhash_response.json new file mode 100644 index 00000000..6a72172d --- /dev/null +++ b/Connector/xmr/rpcschemas/getblockbyhash_response.json @@ -0,0 +1,70 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "title": "", + "description": "", + "type": "object", + "properties": { + "blob": { + "type": "string" + }, + "block_header": { + "type": "object", + "properties": { + "block_size": { + "type": "integer" + }, + "depth": { + "type": "integer" + }, + "difficulty": { + "type": "integer" + }, + "hash": { + "type": "string" + }, + "height": { + "type": "integer" + }, + "major_version": { + "type": "integer" + }, + "minor_version": { + "type": "integer" + }, + "nonce": { + "type": "integer" + }, + "num_txes": { + "type": "integer" + }, + "orphan_status": { + "type": "boolean" + }, + "prev_hash": { + "type": "string" + }, + "reward": { + "type": "integer" + }, + "timestamp": { + "type": "integer" + } + } + }, + "credits": { + "type": "integer" + }, + "json": { + "type": "string" + }, + "miner_tx_hash": { + "type": "string" + }, + "status": { + "type": "string" + }, + "untrusted": { + "type": "boolean" + } + } +} \ No newline at end of file diff --git a/Connector/xmr/rpcschemas/getblockbynumber_request.json b/Connector/xmr/rpcschemas/getblockbynumber_request.json new file mode 100644 index 00000000..9affd11b --- /dev/null +++ b/Connector/xmr/rpcschemas/getblockbynumber_request.json @@ -0,0 +1,14 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "title": "", + "description": "", + "type": "object", + "properties": { + "blockNumber" : { + "type": "string" + } + }, + "required": [ + "blockNumber" + ] +} \ No newline at end of file diff --git a/Connector/xmr/rpcschemas/getblockbynumber_response.json b/Connector/xmr/rpcschemas/getblockbynumber_response.json new file mode 100644 index 00000000..6a72172d --- /dev/null +++ b/Connector/xmr/rpcschemas/getblockbynumber_response.json @@ -0,0 +1,70 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "title": "", + "description": "", + "type": "object", + "properties": { + "blob": { + "type": "string" + }, + "block_header": { + "type": "object", + "properties": { + "block_size": { + "type": "integer" + }, + "depth": { + "type": "integer" + }, + "difficulty": { + "type": "integer" + }, + "hash": { + "type": "string" + }, + "height": { + "type": "integer" + }, + "major_version": { + "type": "integer" + }, + "minor_version": { + "type": "integer" + }, + "nonce": { + "type": "integer" + }, + "num_txes": { + "type": "integer" + }, + "orphan_status": { + "type": "boolean" + }, + "prev_hash": { + "type": "string" + }, + "reward": { + "type": "integer" + }, + "timestamp": { + "type": "integer" + } + } + }, + "credits": { + "type": "integer" + }, + "json": { + "type": "string" + }, + "miner_tx_hash": { + "type": "string" + }, + "status": { + "type": "string" + }, + "untrusted": { + "type": "boolean" + } + } +} \ No newline at end of file diff --git a/Connector/xmr/rpcschemas/getfeeperbyte_request.json b/Connector/xmr/rpcschemas/getfeeperbyte_request.json new file mode 100644 index 00000000..9a0cc5c9 --- /dev/null +++ b/Connector/xmr/rpcschemas/getfeeperbyte_request.json @@ -0,0 +1,7 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "title": "", + "description": "", + "type": "object", + "properties": {} +} \ No newline at end of file diff --git a/Connector/xmr/rpcschemas/getfeeperbyte_response.json b/Connector/xmr/rpcschemas/getfeeperbyte_response.json new file mode 100644 index 00000000..63531d38 --- /dev/null +++ b/Connector/xmr/rpcschemas/getfeeperbyte_response.json @@ -0,0 +1,14 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "title": "", + "description": "", + "type": "object", + "properties": { + "feePerByte" : { + "type" : "integer" + } + }, + "required": [ + "feePerByte" + ] +} \ No newline at end of file diff --git a/Connector/xmr/rpcschemas/getheight_request.json b/Connector/xmr/rpcschemas/getheight_request.json new file mode 100644 index 00000000..9a0cc5c9 --- /dev/null +++ b/Connector/xmr/rpcschemas/getheight_request.json @@ -0,0 +1,7 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "title": "", + "description": "", + "type": "object", + "properties": {} +} \ No newline at end of file diff --git a/Connector/xmr/rpcschemas/getheight_response.json b/Connector/xmr/rpcschemas/getheight_response.json new file mode 100644 index 00000000..72b49795 --- /dev/null +++ b/Connector/xmr/rpcschemas/getheight_response.json @@ -0,0 +1,18 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "title": "", + "description": "", + "type": "object", + "properties": { + "latestBlockIndex": { + "type": "integer" + }, + "latestBlockHash" : { + "type" : "string" + } + }, + "required": [ + "latestBlockIndex", + "latestBlockHash" + ] +} \ No newline at end of file diff --git a/Connector/xmr/rpcschemas/getspendproof_request.json b/Connector/xmr/rpcschemas/getspendproof_request.json new file mode 100644 index 00000000..54a32c01 --- /dev/null +++ b/Connector/xmr/rpcschemas/getspendproof_request.json @@ -0,0 +1,18 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "title": "", + "description": "", + "type": "object", + "properties": { + "txid" : { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "txid", + "message" + ] +} \ No newline at end of file diff --git a/Connector/xmr/rpcschemas/getspendproof_response.json b/Connector/xmr/rpcschemas/getspendproof_response.json new file mode 100644 index 00000000..1bc4af6f --- /dev/null +++ b/Connector/xmr/rpcschemas/getspendproof_response.json @@ -0,0 +1,14 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "title": "", + "description": "", + "type": "object", + "properties": { + "signature": { + "type": "string" + } + }, + "required": [ + "signature" + ] +} \ No newline at end of file diff --git a/Connector/xmr/rpcschemas/gettxproof_request.json b/Connector/xmr/rpcschemas/gettxproof_request.json new file mode 100644 index 00000000..a0818a28 --- /dev/null +++ b/Connector/xmr/rpcschemas/gettxproof_request.json @@ -0,0 +1,22 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "title": "", + "description": "", + "type": "object", + "properties": { + "txid" : { + "type": "string" + }, + "address": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "txid", + "address", + "message" + ] +} \ No newline at end of file diff --git a/Connector/xmr/rpcschemas/gettxproof_response.json b/Connector/xmr/rpcschemas/gettxproof_response.json new file mode 100644 index 00000000..1bc4af6f --- /dev/null +++ b/Connector/xmr/rpcschemas/gettxproof_response.json @@ -0,0 +1,14 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "title": "", + "description": "", + "type": "object", + "properties": { + "signature": { + "type": "string" + } + }, + "required": [ + "signature" + ] +} \ No newline at end of file diff --git a/Connector/xmr/utils.py b/Connector/xmr/utils.py index b7e4a155..46a33976 100644 --- a/Connector/xmr/utils.py +++ b/Connector/xmr/utils.py @@ -1,5 +1,8 @@ #!/usr/bin/python3 +import os +from posixpath import join from .constants import * +from logger import logger def getMethodSchemas(name): @@ -12,3 +15,15 @@ def getRequestMethodSchema(name): def getResponseMethodSchema(name): return RPC_JSON_SCHEMA_FOLDER + name + SCHEMA_CHAR_SEPARATOR + RESPONSE + SCHEMA_EXTENSION + + +def getWalletName(): + walletPath = "../../packages/nodechain-monero-wallet/wallet-dir" + if not os.path.exists(walletPath): + logger.printError(f"Path to wallet folder doesn't exist: {walletPath}") + return + + files = [f for f in os.listdir(walletPath) if os.path.isfile(join(walletPath, f))] + walletFile = [f for f in files if f.endswith(".keys")] + + return os.path.splitext(walletFile[0])[0] diff --git a/docker-compose/testnet/xmr.yml b/docker-compose/testnet/xmr.yml index 6f106f18..5bc82fb6 100644 --- a/docker-compose/testnet/xmr.yml +++ b/docker-compose/testnet/xmr.yml @@ -3,10 +3,20 @@ services: monerod: build: ../../packages/nodechain-monerod image: monerod - command: --stagenet --p2p-bind-ip=0.0.0.0 --p2p-bind-port=38080 --rpc-bind-ip=0.0.0.0 --rpc-bind-port=38081 --non-interactive --confirm-external-bind + command: --stagenet --p2p-bind-ip=0.0.0.0 --p2p-bind-port=38080 --rpc-bind-ip=0.0.0.0 --rpc-bind-port=38081 --non-interactive --confirm-external-bind --prune-blockchain volumes: - ${BLOCKCHAIN_PATH}/bitmonero:/home/monero/.bitmonero - user: "${UID}:${GID}" + + wallet: + build: ../../packages/nodechain-monero-wallet + image: monero-wallet + command: --daemon-address=monerod:38081 --stagenet --disable-rpc-login --trusted-daemon --rpc-bind-port=38088 --rpc-bind-ip=0.0.0.0 --confirm-external-bind --non-interactive --log-level=4 + volumes: + - ${BLOCKCHAIN_PATH}/bitmonero:/home/monero/.bitmonero + depends_on: + - monerod + ports: + - "60000:38088" connector: build: ../../Connector diff --git a/packages/nodechain-monero-wallet/Dockerfile b/packages/nodechain-monero-wallet/Dockerfile new file mode 100644 index 00000000..3fa66815 --- /dev/null +++ b/packages/nodechain-monero-wallet/Dockerfile @@ -0,0 +1,32 @@ +FROM ubuntu:latest +# Create a user if required +RUN useradd -r monero +# Setup and cleanup of the packages required +RUN apt-get update \ + && apt-get install -y curl \ + && rm -rf /var/lib/apt/lists/* +# Declare the environment variables (version, path, data-dir etc) +ENV MONERO_VERSION=0.17.3.0 +ENV MONERO_SHA256=ac18ce3d1189410a5c175984827d5d601974733303411f6142296d647f6582ce +ENV MONERO_DATA=/home/monero/.bitmonero +# Get the compiled binaries and extract them +RUN curl https://dlsrc.getmonero.org/cli/monero-linux-x64-v$MONERO_VERSION.tar.bz2 -O &&\ + echo "$MONERO_SHA256 monero-linux-x64-v$MONERO_VERSION.tar.bz2" | sha256sum -c - &&\ + tar -xvf monero-linux-x64-v$MONERO_VERSION.tar.bz2 -C /opt +# RUN wget https://dlsrc.getmonero.org/cli/monero-linux-x64-v${MONERO_VERSION}.tar.bz2 +# RUN tar -xf *.tar.bz2 -C /opt +# Cleanup the workspace +RUN rm *.tar.bz2 +# Append the bin folder to the %PATH% +ENV PATH=/opt/monero-x86_64-linux-gnu-v${MONERO_VERSION}:$PATH +# Mount volume +VOLUME ["/home/monero/.bitmonero"] +# Expose required ports (both testnet & mainnet) +EXPOSE 18088 28088 38088 +# Copy wallet directory +COPY wallet-dir /wallet-dir +# Copy and define the entrypoint +COPY entrypoint.sh /entrypoint.sh +ENTRYPOINT ["sh", "/entrypoint.sh"] +# Define the default command +CMD ["monero-wallet-rpc"] \ No newline at end of file diff --git a/packages/nodechain-monero-wallet/entrypoint.sh b/packages/nodechain-monero-wallet/entrypoint.sh new file mode 100644 index 00000000..52aa4ea1 --- /dev/null +++ b/packages/nodechain-monero-wallet/entrypoint.sh @@ -0,0 +1,29 @@ +#!/bin/sh +set -e + +if [ $(echo "$1" | cut -c1) = "-" ]; then + echo "$0: assuming arguments for monero-wallet-rpc" + + set -- monero-wallet-rpc "$@" +fi + +if [ $(echo "$1" | cut -c1) = "-" ] || [ "$1" = "monero-wallet-rpc" ]; then + + echo "$0: cleaning wallets in $MONERO_DATA" + + rm -rf "$MONERO_DATA/wallet-dir" + + echo "$0: setting directory $MONERO_DATA" + + mkdir -p "$MONERO_DATA" + mv "./wallet-dir" "$MONERO_DATA/wallet-dir" + chmod 700 "$MONERO_DATA" + chown -R monero "$MONERO_DATA" + + echo "$0: setting data directory to $MONERO_DATA" + + set -- "$@" --wallet-dir="$MONERO_DATA/wallet-dir" --log-file="$MONERO_DATA/debug.log" # --config-file="$MONERO_DATA/monero-wallet-cli.conf" +fi + +echo +exec "$@" \ No newline at end of file diff --git a/packages/nodechain-monero-wallet/wallet-dir/swapper-stagenet b/packages/nodechain-monero-wallet/wallet-dir/swapper-stagenet new file mode 100644 index 00000000..76bbb4ca Binary files /dev/null and b/packages/nodechain-monero-wallet/wallet-dir/swapper-stagenet differ diff --git a/packages/nodechain-monero-wallet/wallet-dir/swapper-stagenet.keys b/packages/nodechain-monero-wallet/wallet-dir/swapper-stagenet.keys new file mode 100644 index 00000000..20e721d4 Binary files /dev/null and b/packages/nodechain-monero-wallet/wallet-dir/swapper-stagenet.keys differ diff --git a/packages/nodechain-monerod/Dockerfile b/packages/nodechain-monerod/Dockerfile index 66b186df..13c8c2ac 100644 --- a/packages/nodechain-monerod/Dockerfile +++ b/packages/nodechain-monerod/Dockerfile @@ -1,34 +1,30 @@ -# Usage: docker run --restart=always -v /var/data/blockchain-xmr:/root/.bitmonero -p 18080:18080 -p 18081:18081 --name=monerod -td kannix/monero-full-node -FROM debian:bullseye-slim AS build - -ENV MONERO_VERSION=0.17.2.3 MONERO_SHA256=8069012ad5e7b35f79e35e6ca71c2424efc54b61f6f93238b182981ba83f2311 - -RUN apt-get update && apt-get install -y curl bzip2 gosu - -WORKDIR /root - +FROM ubuntu:latest +# Create a user if required +RUN useradd -r monero +# Setup and cleanup of the packages required +RUN apt-get update \ + && apt-get install -y curl \ + && rm -rf /var/lib/apt/lists/* +# Declare the environment variables (version, path, data-dir etc) +ENV MONERO_VERSION=0.17.3.0 +ENV MONERO_SHA256=ac18ce3d1189410a5c175984827d5d601974733303411f6142296d647f6582ce +ENV MONERO_DATA=/home/monero/.bitmonero +# Get the compiled binaries and extract them RUN curl https://dlsrc.getmonero.org/cli/monero-linux-x64-v$MONERO_VERSION.tar.bz2 -O &&\ echo "$MONERO_SHA256 monero-linux-x64-v$MONERO_VERSION.tar.bz2" | sha256sum -c - &&\ - tar -xvf monero-linux-x64-v$MONERO_VERSION.tar.bz2 &&\ - rm monero-linux-x64-v$MONERO_VERSION.tar.bz2 &&\ - cp ./monero-x86_64-linux-gnu-v$MONERO_VERSION/monerod . &&\ - rm -r monero-* - -FROM debian:bullseye-slim - -RUN useradd -ms /bin/bash monero && mkdir -p /home/monero/.bitmonero && chown -R monero:monero /home/monero/.bitmonero -USER monero -WORKDIR /home/monero - -COPY --chown=monero:monero --from=build /root/monerod /home/monero/monerod - -VOLUME /home/monero/.bitmonero - -EXPOSE 18080 18081 38080 38081 - - -COPY --chown=monero:monero entrypoint.sh ./entrypoint.sh -RUN chmod +x entrypoint.sh -ENTRYPOINT ["/home/monero/entrypoint.sh"] - -ENTRYPOINT ["./monerod"] \ No newline at end of file + tar -xvf monero-linux-x64-v$MONERO_VERSION.tar.bz2 -C /opt +# RUN wget https://dlsrc.getmonero.org/cli/monero-linux-x64-v${MONERO_VERSION}.tar.bz2 +# RUN tar -xf *.tar.bz2 -C /opt +# Cleanup the workspace +RUN rm *.tar.bz2 +# Append the bin folder to the %PATH% +ENV PATH=/opt/monero-x86_64-linux-gnu-v${MONERO_VERSION}:$PATH +# Mount volume +VOLUME ["/home/monero/.bitmonero"] +# Expose required ports (both testnet & mainnet) +EXPOSE 18080 18081 28080 28081 38080 38081 +# Copy and define the entrypoint +COPY entrypoint.sh /entrypoint.sh +ENTRYPOINT ["sh", "/entrypoint.sh"] +# Define the default command +CMD ["monerod"] \ No newline at end of file diff --git a/packages/nodechain-monerod/entrypoint.sh b/packages/nodechain-monerod/entrypoint.sh index f3a803f1..4476be3b 100644 --- a/packages/nodechain-monerod/entrypoint.sh +++ b/packages/nodechain-monerod/entrypoint.sh @@ -1,21 +1,21 @@ -#!/bin/bash +#!/bin/sh set -e -# if thrown flags immediately, -# assume they want to run the blockchain daemon -if [ "${1:0:1}" = '-' ]; then - set -- monerod "$@" +if [ $(echo "$1" | cut -c1) = "-" ]; then + echo "$0: assuming arguments for monerod" + + set -- monerod "$@" fi -# if they are running the blockchain daemon, -# make efficient use of memory -if [ "$1" = 'monerod' ]; then - numa='numactl --interleave=all' - if $numa true &> /dev/null; then - set -- $numa "$@" - fi - exec "$@" +if [ $(echo "$1" | cut -c1) = "-" ] || [ "$1" = "monerod" ]; then + mkdir -p "$MONERO_DATA" + chmod 700 "$MONERO_DATA" + chown -R monero "$MONERO_DATA" + + echo "$0: setting data directory to $MONERO_DATA" + + set -- "$@" --data-dir="$MONERO_DATA" # --non-interactive --config-file="$MONERO_DATA/monerod.conf" fi -# otherwise, don't get in their way -exec "$@" +echo +exec "$@" \ No newline at end of file