I'm not entirely sure how this happens, but I came across a node that
was failing here because the trigger didn't exist -- possibly from a
partial upgrade?
In any case, the `IF EXISTS` makes it more lenient.
The CLI wallets `print_locked_stakes` was buggy, overly verbose, and
missing pertinent information. This overhauls it.
Details are below; the quick differences:
- show the staking requirement
- make key image output optional with a +key_images flag on the command
- fix various bugs such as just showing the first contribution as the
"total" contribution
- add the wallet address of extra contributions, rather than just the
key image with no other info.
- put your own contributions first, and mark them as such
- show totals of other contributors
- sort service nodes to put unlocking nodes first; among unlocking and
non-unlocking nodes we sort by hex pubkey string.
- sort locked dereg outputs by unlock height
- considerable reformatting of how things are displayed
---
Output now looks like this:
First we have 1-2 lines of general info:
Service Node: abcdef123456...
Unlock Height: 1234567 (omitted if not unlocking)
If there are other contributors then we print a total line such as:
Total Contributions: 15000 OXEN of 15000 OXEN required
For our own contribution, when we have a single contribution, we use one of:
Your Contribution: 5000 OXEN (Key image: abcdef123...)
Your Contribution: 5000 OXEN of 15000 OXEN required (Key image: abcdef123...)
(the second one applies if we are the only contributor so far).
If we made multiple contributions then:
Your Contributions: 5000 OXEN in 2 contributions:
Your Contributions: 5000 OXEN of 15000 OXEN required in 2 contributions:
(the second one if we are the only contributor so far).
This is followed by the individual contributions:
‣ 4000.5 OXEN (Key image: abcdef123...)
‣ 999.5 OXEN (Key image: 789cba456...)
If there are other contributors then we also print:
Other contributions: 10000 OXEN from 2 contributors:
• 1234.565 OXEN (T6U7YGUcPJffbaF5p8NLC3VidwJyHSdMaGmSxTBV645v33CmLq2ZvMqBdY9AVB2z8uhbHPCZSuZbv68hE6NBXBc51Gg9MGUGr)
Key image 123456789...
• 8765.435 OXEN (T6Tpop5RZdwE39iBvoP5xpJVoMpYPUwQpef9zS2tLL8yVgbppBbtGnzZxzkSp53Coi88wbsTHiokr7k8MQU94mGF1zzERqELK)
‣ 7530 OXEN (Key image: 23456789a...)
‣ 1235.435 OXEN (Key image: 3456789ab...)
If we aren't showing key images then all the key image details get omitted.
---
Locked key images get overhauled too; it wasn't at all clear from the
output *why* these are locked (i.e. these are locked contributions of
failed SNs):
Locked Stakes due to Service Node Deregistration:
‣ 234.567 OXEN (Unlock height 1234567; Key image: abcfed999...)
‣ 5000 OXEN (Unlock height 123333; Key image: cbcfef989...)
With batching, individual blocks can have a negative coinbase emission
because the tx fee gets added to the batch rewards database and not paid
out immediately, which then results in an negative overflow to a value
close to 2^64. Thus a block with no payout and a tx fee will have an
erroneous huge positive coinbase emission when queried via
`get_coinbase_tx_sum`. For example block 1094068 queried with:
{"jsonrpc":"2.0","id":"0","method":"get_coinbase_tx_sum","params":{"height": 1094068, "count": 1}}
returns:
{
"jsonrpc": "2.0",
"id": "0",
"result": {
"burn_amount": 0,
"emission_amount": 18446744073699378616,
"fee_amount": 10173000,
"status": "OK"
}
}
This commit fixes it by making the values signed (and also serves as an
example of why unsigned integers are usually the wrong choice):
{
"jsonrpc": "2.0",
"id": "0",
"result": {
"burn_amount": 0,
"emission_amount": -10173000,
"fee_amount": 10173000,
"status": "OK"
}
}
Profiling shows noticeable CPU spend in allocating memory for this
vector (which makes sense, since we are looping through ~1700 nodes and
building a reward vector for each one). Avoid it by reusing a single
vector that gets cleared (but not reallocated more than a handful of
times).
This reduces batching CPU time in a debug build by about 12%; curiously
I didn't find a noticeable reduction in a release build.
Use intrinsic 128-bit types when supported by the compiler; the
operations on them are a bit faster than the two-uint64_t
implementations we do not, and this shaves about 7% off the batch
processing time (which makes a lot of mul128_div64 calls).
Also removes a bunch of unused, useless epee crap from int-util.h.
Converting between internal addresses and string wallet addresses is
surprisingly expensive (partly because a keccak hash is involved);
normally on the blockchain that doesn't matter because string
conversions are rare, but batching exposed some code paths that do the
conversion a lot.
This makes two optimizations to considerably speed up batching
processing time:
1. Add an address string hash for batch addresses. We don't see that
many, but we tend to see the same addresses for *every* block. By
caching it we can considerably reduce the time needed to do the
actual conversions.
2. In many places we don't really need strings at all: we can work just
with the address_infos (which are cheap). This eliminates some of
the places we use addresses and pushes address_infos further through
the code.
In total, this plus the previous optimization drop batch processing time
by this cuts batch processing CPU time by about 85%, roughly half from
this optimization and roughly half from the store-offsets optimization.
On a debug build, timing mainnet resyncing from just before HF19 to
current:
- neither optimization: 223.60s spent processing batch jobs (of 282s
total recalculating subsystems).
- just offsets: 131s spent in batch processing
- both optimizations: 33s spent in batch processing (down to 60s total
recalculating).
On a release build:
- before: 107.35s (4.73s snl; 95.55s batch)
- after: 28.27s (4.66s snl; 0.00s ons; 21.72s batch)
Batch timing was being reported as 0s, even though it is taking up the
vast majority of the time as of the HF block.
Reduce the block processing size to 500 blocks at a time rather than
1000.
Change when we print status updates to print once duration passes a 10s
threshold rather than every 10*1000 blocks.
This latter change probably also makes oxend more reliable on
low-powered servers because it also guards the systemd status update
message (which is needed to give us more watchdog time).
When the sqlite batching database is resyncing it is dependant on the
service node list state being correct at the time the block is added to
the batching database. When syncing a singular module this sometimes is
not the case as the service node list state may be ahead or behind. This
patch simply ensures that when the batching database is behind the
service node list is reset back to that point in time.
The RPC call to return accrued balances currently returns some 0s,
because the database has sub-atomic (but non-zero) stored amounts.
This commit skips those when querying accrued earnings.
wallet2 currently exposes a bug where it shows the next payout being +1
interval blocks from now one block too soon (i.e. if I earn a reward on
block 1234 then it should give me 1234 as my next payout height up until
we actually get block 1234 with the payout).
db_sqlite.cpp was already getting this behaviour by passing in height-1,
but that feels like a workaround for an off-by-one in the function
itself. This fixes the function (and removes the -1 from
db_sqlite.cpp).
- When calculating the offset the calculation here is overflowing; since
they are `uint64_t`s where overflow is well-defined that doesn't
actually break anything (the overflowed value overflows in the other
direction when added, and works as the intended subtraction), but it
feels a bit icky. Rearranging the logic avoids it.
- If given a small height (e.g. 3) the next payout height would come out
as a large positive number (close to uint64_t max). The change above
avoids this as well.
This adds detail to the balance command of the CLI wallet to show how
much has been batched for each address and also summarises when the next
payout is.
It also includes additional fields to get_balance rpc endpoint on the
oxen-wallet-rpc so the user can check on the status of their accrued
funds.
If we pass the blob into parse_and_validate_tx_from_blob we get
`deserialization or varint failed` error logs, which are harmless bug
annoying. This catches the empty tx blob case earlier and logs at a
lesser severity.
If on_transaction_relayed fails to parse, it returns a null_hash, but
that wasn't being detected here.
Also eliminates calling `on_transaction_relayed(tx_blob)` twice.
Some node on the network apparently has a corrupted DB and is spewing
empty tx blobs onto the network. Detect such a case rather than
broadcasting broken empty txes.
We figure out, when parsing a blockchain-confirmed transaction, what the
change is but never properly set that in the new
confirmed_transfer_details entry that we create from the
unconfirmed_transfer_details, and the latter only has the *actual*
change but doesn't know about outputs we sent to ourself.
This commit fixes it by updating the change value when such a case
occurs, which fixes a wrong output & running total bug in csv exports.
Received inputs were being handled incorrectly when importing key
images: only the *first* payment received was being removed, but it
can easily happen that we have multiple payments to ourselves in the
same wallet (for example, if we send a fixed amount to ourselves then
almost always send two non-zero amounts to ourself: the amount + the
change).
This would result in (n-1) "in" outputs for the transaction still
showing up in the output, along with the "out" transaction (which
contains the overall net transfer amount). For example:
- Alice sends 100 + 12.3 change to herself.
- Bob has Alice's view keys, opens a view-only wallet, sees 100 and 12.3
as two separate inputs from the same transaction.
- Alice provides a key image export to Bob to verify the account
- Bob imports.
Bob's export would now show:
in 12.3
out 0
(The inputs of the same transaction are apparently ordered randomly, so
it could also be 'in 100'/'out 0')
and the running total would be 12.3 too high (or 100 too high if the 100
got left instead of the 12.3).
This fixes it by removing *all* matching payments when we import key
images instead of just the first one.
Cleans up some messy code.
Reformats the CSV output to be a little cleaner (in both code and
result), using fmt:
- change second "amount" field to "sent_amount"
- don't unnecessarily quote the subaddr indices field (only quote when
more than one need to be listed as comma-separated).
- change "checkpoint" field output to "yes"/"no" rather than
"checkpointed"/"no".
- Adds spacing between fields which makes it a little easier to read and
should still parse identically.
- Date format also changes somewhat (because fmt is now formatting it)
and includes " UTC" to clarify.
Miscellanous crap that I couldn't help but cleanup while working in
wallet2 to solve the export csv issues:
- To celebrate the 10 year anniversary of god inventing `auto` we
replace some obtuse code that was trying to make itself look bigger by
typing out massive obvious types.
- Remove the single remaining tab in wallet2.cpp to get wallet2.cpp from
being 99.9993% tab-free too 100.0000000% tab free.
- Fix THROW_WALLET_EXCEPTION_IF calls that checked for not-found *after*
another check that already dereferenced the iterator.
- Make `get_attribute` interface less stupid by returning an optional
string instead of a bool with an out string argument.
- Simplify various std::holds_alternative + var::get combinations with a
single std::get_if.
- Optimize and DRY hex conversion of payment id in make_transfer_view.
The existing code was duplicated 4 times but also was inefficiently
performing extra string allocations via multiple substr calls.
- Loki -> Oxen in a wallet error message.
- Initialize confirmed_transfer_details members inline rather than using
an obtuse constructor.
- Apply some C++17 `if` initializer syntatic sugar.
- Don't use `0 != pointer` to test for null
- Don't use a linear scan of a std::vector to do what an unordered_set
is meant to to.
- Replace NULL with nullptr
- eliminate boost::format from wallet2
- eliminate boost::lexical_cast from wallet2
wallet2 expects to get back the UINT64_MAX value here for a
fully-reserved service node: if it does, it recognizes the node is full
and goes to look for reserved contribution spots.
We don't do anything differently for a nullopt versus an empty vector,
so just return an empty vector for both not-at-the-hf and no-payments
cases.
(This also fixes a segfault and/or chainsync bug in the previous commit
because the optional is dereferenced without checking when on hf19).
Fix edge case where the block producer has garbage in the db: the code
that clears it happens when we *accept* the block, but we can end up
here before then, when we produce the block, so just return empty in
such a case.
On devnet we don't have a storage server, and so storage ports are left
uninitialized and effectively become random ports on the network. This
initializes them to 0, and avoids comparing SS ports for devnet for the
duplicate ip/ports warning.
Add a `prepared_bind` that lets you get a prepared statement and bind
parameters to it in one shot.
Add comments to the prepared_* methods.
Fix test suite bug in sqlite testing wrapper added in the earlier
prepared statement commit: it was selecting values from the current
(new, empty) database rather than the passed-in one.
After the batching HF we now have a "reward" field in the block header
which is confusingly different to "miner_reward". This renames
miner_reward to coinbase_payouts to clarify that this amount is the
amount actually paid out in the coinbase vs the reward accumulated into
the batching DB.
Also fixes a minor bug where the reward would only show the reward of
the first vout instead of summing all the vouts.
It is not uncommon to have nodes get decommissioned after a hardfork,
either due to lack of updating or issues with the release. This
implements a 7 day grace period where nodes that do get decommissioned
will not progress into a deregistration (and being hit with the 30 day
funds locked penalty).
Using SQLite::Statement directly requires sqlite to re-prepare the
statement every time it is executed; going via our `prepared_st` wrapper
caches (per thread) and reuses previously prepared statements for better
performance.
(It also, in some cases, simplifies the code a bit).
Adds two slightly different versions of prepare_registration: one that
works with the existing 4-person registrations (used up to the hard
fork), and one that produces HF19 amount-based registrations.
This also overhauls the questions to be a bit nicer to input;
specifically:
- allow "max" and "min" as stake amount options, and make "max" the
default.
- eliminate the "do you want to contribute the whole stake?" question
entirely. We instantly figure that out if you choose "max" (or enter
the 15000 manually).
- eliminate the "how many contributors?" question. Instead we just keep
taking additional contributors until you stop entering them.
- move the fee to later, after you've provided contributor info (if not
a full stake).
There is, unfortunately, a *huge* amount of duplication here: I copy and
pasted the entire HF18 registration code and just eliminated the
portions parts of it. This is temporary: as soon as we are into HF19 we
can eliminate the HF18 version entirely.
This adds a new tx registration interpretation for HF19+ by repurposing
the fields of the registration:
- `expiration` becomes `hf_or_expiration`; for "new" registrations it
contains the hardfork number (e.g. 19 for HF19), but the data layout
on chain doesn't change: essentially we determine whether it's a new
registration based on whether the field is <= 255 (interpret as HF) or
not (interpret as expiration).
Changes in "new" registrations:
- stake amounts are atomic OXEN rather than portions. This lets us skip
a whole bunch of fiddling around with amounts that was necessary to
deal with integer truncation when converting between amounts and
portions.
- the fee in the registration data is now a value out of 10000 instead
of a portion (i.e. value out of 2^64-4). This limits fee precision to
a percentage with two decimal places instead of ~17 decimal places.
Internally we still convert this to a portion when processing the
registration for service_node_states, but this makes the registration
itself much simpler and easier to work with (as a human).
- HF19+ registrations no longer have an expiry timestamp (though they do
depend on the hardfork, so they "expire" whenever the next hard fork).
The expiry timestamp was really only there to avoid a registration
amount decreasing too much from the dropping staking requirement.
- Both types are registration are still permitted for HF19, but because
registrations with more than 4 contributors expose bugs in the portion
transfer code (that results in registrations become invalid),
old-style registrations are still limited to 4 contributors.
- HF19 will allow both old and new registrations, so that registrations
generated before the HF will still work, and so that we don't break
testnet which has various "old" registrations on it.
There is a (correct) warning in the calculation that divides by this
value that this code is doing integer division, but then storing in a
float. This fixes the warning, and the intention.
This PR defines contributors to a service node as a small contributor if
they contribute <25% of the nodes locked contributions. If a contributor
is small then they are prevented from unlocking their stake for 30 days
after the node is registered. This was in response to operators getting
frustrated with small contributors immediately unlocking after a node
was registered.
If you imagine the following node contribution structure:
Operator: 25%
Contributor 1: 65%
Contributor 2: 10%
Total: 100%
Node is registered on day 0. On Day 1 both the operator and Contributor
1 will be able to unlock their stake and the node begins its 15 day
unlock period.
Contributor 2 however will be prevented from unlocking until day 30.
At this point they will be able to unlock and begin the nodes 15 day
unlock period.
This allows a user to query the daemon and ask for the accrued balance
of oxen rewards that have been batched but not yet paid out.
The endpoint takes in an array of addresses (Strings) and returns an
array of atomic oxen amounts (integers) that reflect the current
database balances for those requested addresses.
For example an address has accrued 2x batch payments of 16.5 oxen but
has not yet been paid out will show 33000000000 being the atomic amount
in the database.
- Replace all cryptonote_config macros with constexpr variables. Some
become integer types, some become chrono types.
- generally this involved removing a "CRYPTONOTE_" prefix since the
values are now in the `cryptonote` namespace
- some constants are grouped into sub-namespaces (e.g.
cryptonote::p2p)
- deprecated constants (i.e. for old HFs) are in the `cryptonote::old`
namespace.
- all the magic hash key domain separating strings are now in
cryptonote::hashkey::WHATEVER.
- Move some economy-related constants to oxen_economy.h instead
- Replaced the BLOCKS_EXPECTED_IN_DAYS constexpr functions with more
straightforward `BLOCKS_PER_DAY` value (i.e. old
`BLOCKS_EXPECTED_IN_DAYS(10)` is now `BLOCKS_PER_DAY * 10`.
- Replaced `network_version` unscoped enum with a scoped enum
`cryptonote::hf`, replacing all the raw uint8_t values where it was
currently accepted with the new `hf` type.
- Made `network_type` a scoped enum so that it now has to be qualified
(network_type::TESTNET) and can't be arbitrarily/unintentionally
converted to/from an int.
- HARDFORK_WHATEVER macros have become cryptonote::feature::WHATEVER
constexpr hf values.
- Add `revision` to rpc hard_fork_info response
- Don't build trezor code at all (previously we were pointlessly
building an empty dummy lib).
A fixed 3750 amount won't work on testnet (and also was set to 3750
atomic units instead of 3750 coins).
This refactor the math a bit so that the amount falls out of the portion
constant when making a registration.
This requires the operator to still contribute 25% of the service node
but another 9 nodes will be allowed to stake to the node makeing 10
contributors total rather than our previous 4.
This updates the coinbase transactions to reward service nodes
periodically rather than every block. If you recieve a service node
reward this reward will be delayed x blocks, if you receive another
reward to the same wallet before those blocks have been completed it
will be added to your total and all will be paid out after those x
blocks has passed.
For example if our batching interval is 2 blocks:
Block 1 - Address A receives reward of 10 oxen - added to batch
Block 2 - Address A receives reward of 10 oxen - added to batch
Block 3 - Address A is paid out 20 oxen.
Batching accumulates a small reward for all nodes every block
The batching of service node rewards allows us to drip feed rewards
to service nodes. Rather than accruing each service node 16.5 oxen every
time they are pulse block leader we now reward every node the 16.5 /
num_service_nodes every block and pay each wallet the full amount that
has been accrued after a period of time (Likely 3.5 days).
To spread each payment evenly we now pay the rewards based on the
address of the recipient. This modulus of their address determines which
block the address should be paid and by setting the interval to our
service_node_batching interval we can guarantee they will be paid out
regularly and evenly distribute the payments for all wallets over this
We could get a rounding error in the contributor spots that would make
the registration fail when passed to oxend. This fixes it by restoring
the missing logic that was accidentally dropped in the
prepare_registration refactor.
Testnet has shown that it is virtually impossible to route around a
checkpoint for a block that had to be rendered unacceptable because it
accepts the future checkpoint which then prevents an alternate block
from being generated at all.
This mitigates it in two ways:
- Don't accept new checkpoint votes before we receive the block
- Delay checkpoint voting & vote distribution by one block (e.g. nodes
will vote on block 12345 only once 12346 is received).
The first allows a manual pop_blocks to remove checkpoints that won't
get re-added (e.g. if the checkpointed block has become unacceptable, as
occurs sometimes in testnet/devnet, but could theoretically occur on
mainnet if we have to do a block reversal).
The second minimizes the number of rejected votes that will occur since
nodes will almost always have the block now when the checkpoint arrives.
Reorders the way questions are asked to flow better. Previously the way
questions was asked was sort of awkward.
The old order, for instance staking a partially open node:
- entire stake?
- fee?
- reserve more?
- how many more?
- operator address?
- operator stake size?
- contributor address?
- how much for contributor?
- more contributors, if any
- not filled okay?
- confirm everything?
where there are related values (e.g. operator addr & stake) intermingled
with around other things (e.g. fee & number of contributors).
With this commit the order is rewritten to:
- operator address?
- entire stake?
- operator stake size?
- fee?
- reserve more?
- how many more?
- contributor 1 addr
- contributor 1 amnt
- more contributors, if any
- not filled okay?
- confirm everything?
Additional changes:
- substantially DRY out the code. There was a huge amount of repeated
code in this section.
- highlight OXEN amounts in cyan.
- I rewrote much of the language to make it clearer and more grammatical
- reformatted the summary table to look a bit better
- the fee in the final summary is highlighted yellow.
- if there are multiple open spots this is now more clearly indicated in
the output and the final summary screen.
Example:
```
$ oxend prepare_registration
2022-04-15 20:11:29.211 I Oxen 'Audacious Aurochs' (v9.2.0-0b38bd982-dev)
Current staking requirement: 15000 OXEN
Enter the OXEN address of the Service Node operator (C/Cancel):
LDoptfyQB3YHbS9cnt2wHdTTj2wtZGPuM48evCFwZpomVajQw4eJ6mDCpXeUNTxsqbTiYytnqEDQNin3XGwp3nReMooMaWG
Will the operator contribute the entire stake? (Y/Yes/N/No/B/Back/C/Cancel): n
The operator contribution must be between 3750 OXEN and 15000 OXEN to meet the staking requirements.
How much OXEN does the operator want to stake? (B/Back/C/Cancel): 5555
Enter operator fee as a percentage of earned rewards [0-100]% (B/Back/C/Cancel): 4.567
Do you want to reserve stakes for specific contributors? (Y/Yes/N/No/B/Back/C/Cancel): y
Number of additional contributors [1-3] (B/Back/C/Cancel): 2
Enter the OXEN address of contributor 1 (B/Back/C/Cancel):
L6JasonXTGW6juHrJgsXTxXH1Jh9u94H8NQ9m4rMwz5a9SZGr2e1cXw9MqnVH6Qx5bTgL5wf7qfvHeNPdwyC63AzMixU5ad
The next contribution must be between 3148.333333333 OXEN and 9445 OXEN to meet the staking requirements.
How much OXEN does contributor 1 want to stake? (B/Back/C/Cancel): 5555
Enter the OXEN address of contributor 2 (B/Back/C/Cancel):
L7jC35E9MnQZu2dS1n8wCqbvVBFpGHJt7iNHgAuEy5is57dzX2uQZDASv4KvwzruxXARxa4omafN6i19QBY7KAcSH1Xz7ZL
The next contribution must be between 1945 OXEN and 3890 OXEN to meet the staking requirements.
How much OXEN does contributor 2 want to stake? (B/Back/C/Cancel): 3000
Total reserved contributions: 14110 OXEN
The total reserved amount (14110 OXEN) is less than the required full stake (15000 OXEN).
The remaining stake (890 OXEN) will be open to contribution from 1 public contributor.
The Service Node will not activate until the full contribution has been filled.
Is this acceptable? (Y/Yes/N/No/B/Back/C/Cancel): y
Registration Summary:
Operator fee (as % of Service Node rewards): 4.567%
Contributor Address Contribution Contr. %
_____________ _____________ _________________ ________
Operator LDoptfyQB..WG 5555.000000000 37.03%
Contributor 1 L6JasonXT..ad 5555.000000000 37.03%
Contributor 2 L7jC35E9M..ZL 3000.000000000 20.00%
(open) (any) 890.000000000 5.93%
Is the staking information above correct? (Y/Yes/N/No/B/Back/C/Cancel):
```
For a open node with 3 open spots the summary table looks like this:
```
Contributor Address Contribution Contr. %
_____________ _____________ _________________ ________
Operator L6JasonXT..ad 6789.000000000 45.26%
(open) (any) >=2737.000000000 >=18.25%
(open) (any)
(open) (any)
```
- The decimal point argument isn't used anywhere.
- change `get_unit()` to return `OXEN` instead of `oxen`
- Add a "strip_zeros" option to print_money that lets you remove
trailing insignificant 0's from the returned amount.
- Add format_money that does print_money (with 0s stripped by default) +
get_unit(). E.g. it returns `"45.67 OXEN"`.
When I issue a `prepare_registration` command the cursor gets positioned
at the beginning of the line instead of the end of the line, so typing
things in results in overwriting the text that I was asked.
E.g.:
```
Current staking requirement: 15000.000000000 oxen
yill the operator contribute the entire stake? (Y/Yes/N/No/C/Cancel):
`-- the y I typed replaced the "W"
```
or:
```
Enter the oxen address for the solo staker (B/Back/C/Cancel):
```
and because the cursor is positioned at the beginning, my address
overwrites the prompt as I type/paste it:
```
L6JasonXTGoxen address for the solo staker (B/Back/C/Cancel):
```
This is caused because we were suspending the readline buffer *after*
printing things out, and something (perhaps local config, or perhaps an
update to libreadline) repositions to cursor at column 0.
This commit suspends the readline handler *before* we print the message,
which makes it sane again:
```
Enter the oxen address for the solo staker (B/Back/C/Cancel): L6JasonXTG
```
Remove misc_language.h: Half of it is unused, half of it is crap doesn't
need to be used, and the two useful things (median calculator and a
scope exit caller) were poorly written.
Rewrote median from scratch and moved it out of epee.
Simplified the scope exit handler and moved it to its own small header
in epee.
openssl is a miserable dependency to fight with, especially for
iOS/Android, and we use it for very little:
- it gets (mis)used to write base64 data to a file in wallet2 for things
like multisig data. However this mode is *not* enabled by default,
basically completely unknown, completely unused, only exists in the
cli wallet, and is just dumb. (Honestly the justification given in
the PR is that "Windows users might want it", presupposing that there
exists Windows users who are capable of generating a multisig wallet
in a CLI-only application and yet are incapable of dealing with binary
files).
- it's a dependency of unbound (in order to do dnssec, I believe).
Unbound itself is fairly useless for Oxen, so I've removed it too:
- it does OpenAlias lookups, which are a Monero thing that has never
been used outside Monero, doesn't work reliably (because it fails
if the result isn't DNSSEC validated) and is pointless when we
have ONS.
- it does DNS resolution on seed nodes, but we have never set seed
nodes by name and just use seed node IPs instead (which seems a
bit better anyway since the DNS lookup leaks some metadata).
- it *was* being used for sha256, but an earlier commit in this PR
already replaced that with libsodium (entirely coincidentally).
- for static deps, it enables HTTPS support for the wallet. However
only the CLI wallet actually supports this (the GUI and mobile wallets
don't), and since oxend hasn't support this for a while I have strong
doubts it is being used anywhere. (Plus wallet3 will do everything
encrypted using zmq/libsodium, so doesn't need this to be secure).
Note here that it is *only* removed by this commit for static builds:
if doing a system build that links to libcurl supporting HTTPS then
HTTPS support will still work.
Libexpat is also gone because it was only there for libunbound.
- Aside from converting code, this commit also:
- Cleans out a bunch of epee garbage that this code touches.
- Removes some of the wipeable_string usage from wallet2 added by
upstream Monero, because that usage was worse than useless: every
instance removed uses a wipeable_string but then *copies the value
into a std::string*, which makes the entire thing useless.
It is, however, *worse* than useless because it is deceptive: a casual
observer would think that the values are being wiped, when in
actuality it only added an extra intermediate buffer that gets wiped
while the final destination doesn't. This deception is worse than
nothing, and so I've removed it.
- Removes epee md5 code. It is entirely unused, and was depending on
the removed hex code.
- Removes a bunch of useless functions from
epee/storages/parserse_base_utils.h: in particular the
exception-to-bool wrappers were only being used in the test suite
(which was dumb: the test suite is perfectly capable of a "does not
throw" assertion).
- De-templatizes the parsing code in parserse_base_utils.h that was only
ever called with a `const char*` "It" (except for one place in the
test suite was which easily fixed), and moved the implementation into
a .cpp file.
We have disabled uPnP by default for nearly a year now (#1423) with no
adverse affects; this commit finishes it off entirely, removing it from
the codebase.
Fixes#1419 -- see discussion in that issue for why UPnP really doesn't
add much utility to Oxen.
All the encoding parts move to oxen-encoding recently; this updates to
the latest version of oxen-mq, adds oxen-encoding, and converts
everything to use oxenc headers rather than the oxenmq compatibility
shims.
This is currently returning all contributions in all service nodes you
are staked to, which causes the mobile wallet to list everyone's stakes
in multi-contribution service nodes as your own.
The wallet needs to be fed a single output plus a sufficient number of
decoys. This transaction was run on the testnet and details were copied
into the test file.
This goes through the remaining code in wallet2 that needed updating to
utilise our newly defined json_rpc methods rather than epee
serialisation to call rpc methods.
The keyring structure contains functions that will take a pending
transaction and fill out the cryptonote::transaction member with
the relevant signature fields ready for serialization.
When building the pending transaction we can call GetFee() to calculate
how much the transaction will cost. It takes a single parameter for the
number of inputs because we will want to specify how many when
estimating.
We then build a list of the potential fees for up to 300 inputs and pass
that to our output selection function which will use it to determine if
the outputs selected will be sufficient to cover the fees. This allows
us to know in advance how much the fees will be rather than trial and
error.
The Transaction Constructor will be used to generate pending
transactions, depending on the type of transaction the pending
transaction class will allow the user to modify items such as tx type
(ONS for example) add additional data to the tx extra field, modify burn
amount etc before finalising the transaction which will select the
necessary outputs, mixins and calculate fees and change amounts. Once
finalised the pending transaction will be forwarded to a signing
structure for further action.
tx scanning for basic transactions working
- TODO: subadresses. The scanning code is there, but it does not
currently know/care about any subaddresses.
daemon comms for basic syncing working
(multi-)wallet sync more or less working properly
- seem to have a dangling shared_ptr somewhere when removing a wallet from
daemon comms, so not working perfectly yet.
Lots of TODOs and cleanup needed, as well as further features of course.