- What's in this Repo?
- Setup
- Usage
- Testing
- Pull Requests
- Developing
- Contributors
- Embedding the C++
- API
This repository holds the C++ source code for the Haven/Monero/CryptoNote cryptography and protocols, plus lightwallet functions.
This repository owes a huge thank you to the MyMonero folks who wrote mymonero-core-cpp from which this repository is forked. We have deep appreciation for the authors, contributors, and advisors of mymonero-core-cpp:
-
luigi1111
-
vtnerd
-
moneromooo-monero
-
ndorf
-
gutenye
So, thank you!
To anyone utilizing this library, please keep in mind, you may see many references to Monero and/or MyMonero in this repository (and in this README) as a result. We are working on cleaning this up for clarity.
-
contrib/monero-core-custom
is a Git submodule which contains a curated subset of the official Haven C/C++ source code -
src
contains all the custom code written for this repo.serial_bridge_index
contains a central JSON interface to a set of central haven-core functions, documented below.
-
This readme is located at
README.md
, and the license is located atLICENSE.txt
.
-
(to use included shell scripts) cmake
-
Boost 1.58 library components
-
system
-
thread
-
If running tests:
unit_test_framework
-
-
monero-core-custom
(see "Setup")
- Run
bin/update_submodules
Simply embed the relevant code in your application, generally via CMake. See CMakeLists.txt
for required files.
One example usage of this code is its transpilation into wasm and JS by mymonero-core-js.
- Run
bin/buildAndRun_tests
to execute Boost test cases.
Please submit any bugs as Issues unless they have already been reported.
Suggestions and feedback are very welcome!
We'll merge nearly anything constructive and relevant.
Contributors credited in releases.
All development happens off the develop
branch like the Gitflow Workflow.
-
If you use a Mac and want to develop within Xcode, run
bin/genXcodeProj
to generate./xcode/TEST.xcodeproj
. Once opened, its build target can be switched from ALL_BUILD to test_all, from which a Build & Run will display test results in the console. -
Branches and PRs should be made from and to the
develop
branch, which gets merged tomaster
for tagged releases
If you want to embed the C++ or build the source in your own project, please take note of the following:
-
slow-hash.c
must be compiled with-maes
-
The Haven source, a slightly modified version of which is a dep of this project, can only be built on versions of iOS >= 9 due to required support for
thread_local
as used bythreadpool.cpp
. -
Not all Haven
.cpp
files which are inmonero-core-custom
must be included formymonero-core-cpp
- such as when their symbols are not required by any code called by this project. SeeCMakeLists.txt
for a list of files required for compilation. -
If you only want to call the C++ directly without using
serial_bridge_index
(described below), then that file-pair does not need to be included in your build. (See mymonero-app-ios link)
- If you are implementing the below-described Send routine yourself (examples: JS, Swift), you should:
- implement the necessary re-entry logic if step2 indicates reconstruction required, and
- (optional) construct the
err_msg
if the error code indicates not enough spendable balance.
Coming soon
For examples see src/serial_bridge_index.cpp
and mymonero-app-ios/MyMoneroCore_ObjCpp.mm.
src/serial_bridge_index
exposes this project's core library functions. Each bridge function takes a string-serialized JSON object as an argument and returns a string-serialized JSON object.
Usage of each of these JSON-bridge functions is demonstrated in tests/test_all.cpp
.
When they fail, some of these functions return only a key-value err_msg
.
-
Some args must be passed as strings, such as
uint64
args likeindex
s andamount
s. -
Some boolean return values may be sent (by Boost) in JSON as strings instead, called
BoolString
below ( e.g."false"
). -
Network type is sent as a string (
NettypeString
below), which can be obtained viaserial_bridge::string_from_nettype()
.
Compressing / reducing size of key names could be a significant optimization, as could a migration to msgpack.
decode_address
-
Args:
nettype_string: NettypeString
,address: String
-
Returns:
err_msg: String
ORpub_spendKey_string: String
,pub_viewKey_string: String
,paymentID_string: String
, andisSubaddress: Boolstring
is_subaddress
-
Args:
nettype_string: NettypeString
,address: String
-
Returns:
err_msg: String
ORretVal: Boolstring
is_integrated_address
-
Args:
nettype_string: NettypeString
,address: String
-
Returns:
err_msg: String
ORretVal: Boolstring
newly_created_wallet
-
Args:
nettype_string: NettypeString
,locale_language_code: String
-
Returns:
err_msg: String
ORmnemonic_string: String
,mnemonic_language: WordsetNameString
,sec_seed_string: String
,address_string: String
,pub_spendKey_string: String
,pub_viewKey_string: String
,sec_viewKey_string: String
, andsec_spendKey_string: String
are_equal_mnemonics
-
Args:
a: String
,b: String
-
Returns:
err_msg: String
ORretVal: Boolstring
mnemonic_from_seed
-
Args:
seed_string: String
wordset_name: WordsetNameString
returned asmnemonic_language
byseed_and_keys_from_mnemonic
andnewly_created_wallet
-
Returns:
err_msg: String
ORretVal: String
seed_and_keys_from_mnemonic
-
Args:
nettype_string: NettypeString
,mnemonic_string: String
-
Returns:
err_msg: String
ORmnemonic_language: WordsetNameString
,sec_seed_string: String
,address_string: String
,pub_spendKey_string: String
,pub_viewKey_string: String
,sec_viewKey_string: String
, andsec_spendKey_string: String
validate_components_for_login
-
Args:
nettype_string: NettypeString
,address_string: String
,sec_viewKey_string: String
,sec_spendKey_string: Optional<String>
,seed_string: Optional<String>
-
Returns:
err_msg: String
ORpub_spendKey_string: String
,pub_viewKey_string: String
,isInViewOnlyMode: Boolstring
, andisValid: Boolstring
address_and_keys_from_seed
-
AKA
create_address
in legacy mymonero-core-js -
Args:
nettype_string: NettypeString
,seed_string: String
-
Returns:
err_msg: String
ORaddress_string: String
,pub_spendKey_string: String
,pub_viewKey_string: String
,sec_viewKey_string: String
, andsec_spendKey_string: String
new_integrated_address
-
Args:
nettype_string: NettypeString
,short_pid: String
,address: String
-
Returns:
err_msg: String
ORretVal: String
new_payment_id
-
Args: empty object
-
Returns:
err_msg: String
ORretVal: String
generate_key_image
-
Args:
sec_viewKey_string: String
,sec_spendKey_string: String
,pub_spendKey_string: String
,tx_pub_key: String
,out_index: UInt32String
-
Returns:
err_msg: String
ORretVal: String
generate_key_derivation
-
Args:
pub: String
,sec: String
-
Returns:
err_msg: String
ORretVal: String
derivation_to_scalar
-
Args:
derivation: String
,output_index: UInt32String
-
Returns:
err_msg: String
ORretVal: String
derive_public_key
-
Args:
derivation: String
,pub: String
,out_index: UInt32String
-
Returns:
err_msg: String
ORretVal: String
derive_subaddress_public_key
-
Args:
derivation: String
,output_key: String
,out_index: UInt32String
-
Returns:
err_msg: String
ORretVal: String
decodeRct
, decodeRctSimple
-
Args:
i: UInt32String
,sk: String
,rv: DecodeRCT_RV
where-
DecodeRCT_RV: Dictionary
withtype: RCTTypeIntString
,ecdhInfo: [DecodeRCT_ECDHInfo]
,outPk: [DecodeRCT_OutPK]
-
RCTTypeIntString: String
corresponding to values inrct::RCTType*
-
DecodeRCT_ECDHInfo: Dictionary
withamount: String
,mask: String
-
DecodeRCT_OutPK: Dictionary
withmask: String
-
-
e.g.
{"i":"1","sk":"9b1529acb638f497d05677d7505d354b4ba6bc95484008f6362f93160ef3e503","rv":{"type":"1","ecdhInfo":[{"mask":"3ad9d0b3398691b94558e0f750e07e5e0d7d12411cd70b3841159e6c6b10db02","amount":"b3189d8adb5a26568e497eb8e376a7d7d946ebb1daef4c2c87a2c30b65915506"},{"mask":"97b00af8ecba3cb71b9660cc9e1ac110abd21a4c5e50a2c125f964caa96bef0c","amount":"60269d8adb5a26568e497eb8e376a7d7d946ebb1daef4c2c87a2c30b65915506"},{"mask":"db67f5066d9455db404aeaf435ad948bc9f27344bc743e3a32583a9e6695cb08","amount":"b3189d8adb5a26568e497eb8e376a7d7d946ebb1daef4c2c87a2c30b65915506"}],"outPk":[{"mask":"9adc531a9c79a49a4257f24e5e5ea49c2fc1fb4eef49e00d5e5aba6cb6963a7d"},{"mask":"89f40499d6786a4027a24d6674d0940146fd12d8bc6007d338f19f05040e7a41"},{"mask":"f413d28bd5ffdc020528bcb2c19919d7484fbc9c3dd30de34ecff5b8a904e7f6"}]}}
- Returns
err_msg: String
ORamount: String
andmask: String
estimated_tx_network_fee
Useful for displaying an estimated fee – To obtain exact fees, see "Creating and Sending Transactions"
-
Args:
fee_per_b: UInt64String
priority: UInt32String
fork_version: UInt8String
-
Returns:
retVal: UInt64String
estimate_rct_tx_size
-
Args:
n_inputs: UInt32String
mixin: UInt32String
n_outputs: UInt32String
extra_size: UInt32String
bulletproof: BoolString
clsag: BoolString
-
Returns:
retVal: UInt32String
As mentioned, implementing the Send procedure without making use of one of our existing libraries or examples involves two bridge calls surrounded by server API calls, and mandatory reconstruction logic, and is simplified by various opportunities to pass values directly between the steps.
The values which must be passed between functions have (almost entirely) consistent names, simplifying integration. The only current exception is the name of the explicit fee_actually_needed
which should be passed to step1 as the optional passedIn_attemptAt_fee
after being received by calling step2 (see below).
- JS implementation of SendFunds
- JS implementation of JSON bridge calls - note
err_code
handling instep1
and comments
-
UnspentOutput: Dictionary
withamount: UInt64String
public_key: String
rct: Optional<String>
global_index: UInt64String
index: UInt64String
tx_pub_key: String
-
CreateTransactionErrorCode: UInt32String
defined inmonero_transfer_utils.hpp
; to remain stable within major versions -
PricingRecord: Dictionary
withblockchain_height: UInt64String
pricing_record: Dictionary
withsig_hex: String
unused1: UInt64String
unused2: UInt64String
unused3: UInt64String
xAG: UInt64String
xAU: UInt64String
xAUD: UInt64String
xBTC: UInt64String
xCAD: UInt64String
xCHF: UInt64String
xCNY: UInt64String
xERU: UInt64String
xGBP: UInt64String
xJPY: UInt64String
xNOK: UInt64String
xNZD: UInt64String
xUSD: UInt64String
-
Args:
sending_amount: UInt64String
is_sweeping: BoolString
from_asset_type: String
to_asset_type: String
priority: UInt32String
of1
–4
fee_per_b: UInt64String
fee_mask: UInt64String
fork_version: UInt8String
unspent_outs: [UnspentOutput]
- fully parsed server responsepr: [PricingRecord]
- fully parsed server responsepayment_id_string: Optional<String>
passedIn_attemptAt_fee: Optional<UInt64String>
-
Returns:
err_code: CreateTransactionErrorCode
==needMoreMoneyThanFound(90)
err_msg: String
required_balance: UInt64String
spendable_balance: UInt64String
OR
err_code: CreateTransactionErrorCode
!=needMoreMoneyThanFound
err_msg: String
OR
mixin: UInt32String
use this for requesting random outputs before step2using_fee: UInt64String
expressed in same currency asfrom_asset_type
change_amount: UInt64String
expressed in same currency asfrom_asset_type
using_outs: [UnspentOutput]
passable directly to step2final_total_wo_fee: UInt64String
expressed in same currency asfrom_asset_type
- Args:
-
from_address_string: String
-
sec_viewKey_string: String
-
sec_spendKey_string: String
-
to_address_string: String
-
from_asset_type: String
-
to_asset_type: String
-
final_total_wo_fee: UInt64String
returned by step1 -
change_amount: UInt64String
returned by step1 -
fee_amount: UInt64String
returned by step1 -
priority: UInt32String
of1
–4
-
fee_per_b: UInt64String
-
fee_mask: UInt64String
-
fork_version: UInt8String
-
using_outs: [UnspentOutput]
returned by step1 -
mix_outs: [MixAmountAndOuts]
defined below -
current_height: UInt64String
obtained from API call -
pr: [PricingRecord]
- fully parsed server response -
unlock_time: UInt64String
-
nettype_string: NettypeString
-
payment_id_string: Optional<String>
MixAmountAndOuts: Dictionary
decoys obtained from API call withamount: UInt64String
outputs: [MixOut]
whereMixOut: Dictionary
withglobal_index: UInt64String
public_key: String
rct: Optional<String>
-
Returns:
tx_must_be_reconstructed: BoolString
==true
fee_actually_needed: UInt64String
pass this back to step1 aspassedIn_attemptAt_fee
OR
err_msg: String
OR
tx_must_be_reconstructed: Boolstring
!=true
serialized_signed_tx: String
tx_hash: String
tx_key: String
-