From 88fb116c539541967c2adb5578df2fb5d47ed25a Mon Sep 17 00:00:00 2001 From: jl777 Date: Sat, 6 Apr 2019 00:55:23 -1100 Subject: [PATCH 01/35] Comments --- src/cc/prices.cpp | 36 ++++++++++++++++++++++++------------ src/komodo_gateway.h | 6 +++--- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/cc/prices.cpp b/src/cc/prices.cpp index cedf05f2b..85e2c645d 100644 --- a/src/cc/prices.cpp +++ b/src/cc/prices.cpp @@ -19,26 +19,38 @@ /* CBOPRET creates trustless oracles, which can be used for making a synthetic cash settlement system based on real world prices; + + 0.5% fee based on betamount, NOT leveraged betamount!! 0.1% collected by price basis determinant 0.2% collected by rekt tx - PricesBet -> +/-leverage, amount, synthetic -> opreturn includes current price - funds are locked into 1of2 global CC address - for first day, long basis is MAX(correlated,smoothed), short is MIN() - reference price is the smoothed of the previous block - if synthetic value + amount goes negative, then anybody can rekt it to collect a rektfee, proof of rekt must be included to show cost basis, rekt price - original creator can liquidate at anytime and collect (synthetic value + amount) from globalfund - 0.5% of bet -> globalfund - - PricesStatus -> bettxid maxsamples returns initial params, cost basis, amount left, rekt:true/false, rektheight, initial synthetic price, current synthetic price, net gain + UniValue PricesBet(uint64_t txfee,int64_t amount,int16_t leverage,std::vector synthetic) + funds are locked into 1of2 global CC address + for first day, long basis is MAX(correlated,smoothed), short is MIN() + reference price is the smoothed of the previous block + if synthetic value + amount goes negative, then anybody can rekt it to collect a rektfee, proof of rekt must be included to show cost basis, rekt price + original creator can liquidate at anytime and collect (synthetic value + amount) from globalfund + 0.5% of bet -> globalfund + + UniValue PricesAddFunding(uint64_t txfee,uint256 bettxid,int64_t amount) + add funding to an existing bet, doesnt change the profit calcs but does make the bet less likely to be rekt - PricesRekt -> bettxid height -> 0.1% to miner, rest to global CC + UniValue PricesSetcostbasis(uint64_t txfee,uint256 bettxid) + in the first day from the bet, the costbasis can (and usually does) change based on the MAX(correlated,smoothed) for long and MIN() for shorts + to calculate this requires a bit of work, so whatever node is first to get the proper calculation confirmed, gets a 0.1% costbasis fee - PricesClose -> bettxid returns (synthetic value + amount) + UniValue PricesRekt(uint64_t txfee,uint256 bettxid,int32_t rektheight) + similarily, any node can submit a rekt tx and cash in on 0.2% fee if their claim is confirmed - PricesList -> all bettxid -> list [bettxid, netgain] + UniValue PricesCashout(uint64_t txfee,uint256 bettxid) + only the actually creator of bet is able to cashout and only if it isnt rekt at that moment + UniValue PricesInfo(uint256 bettxid,int32_t refheight) + all relevant info about a bet + + UniValue PricesList() + a list of all pending and completed bets in different lists */ diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index f7f7874ce..ba15746e0 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1728,7 +1728,7 @@ CScript komodo_mineropret(int32_t nHeight) int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,int32_t nHeight,CScript scriptPubKey) { - int32_t testchain_exemption = 350; + int32_t testchain_exemption = 0; std::vector vopret; char maxflags[KOMODO_MAXPRICES]; double btcusd,btcgbp,btceur; uint32_t localbits[KOMODO_MAXPRICES],pricebits[KOMODO_MAXPRICES],prevbits[KOMODO_MAXPRICES],newprice; int32_t i,j,prevtime,maxflag,lag,lag2,lag3,n,errflag,iter; uint32_t now = (uint32_t)time(NULL); if ( ASSETCHAINS_CBOPRET != 0 && nHeight > 0 ) { @@ -2135,8 +2135,8 @@ void komodo_cbopretupdate(int32_t forceflag) now = (uint32_t)time(NULL); if ( (ASSETCHAINS_CBOPRET & 1) != 0 ) { -if ( komodo_nextheight() > 333 ) // for debug only! - ASSETCHAINS_CBOPRET = 7; +//if ( komodo_nextheight() > 333 ) // for debug only! +// ASSETCHAINS_CBOPRET = 7; size = komodo_cbopretsize(ASSETCHAINS_CBOPRET); if ( Mineropret.size() < size ) Mineropret.resize(size); From 1de369ea40560da31194b1469c9385b8de271f8a Mon Sep 17 00:00:00 2001 From: jl777 Date: Sat, 6 Apr 2019 01:23:21 -1100 Subject: [PATCH 02/35] Prices CC rpc purpose documented --- src/cc/prices.cpp | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/cc/prices.cpp b/src/cc/prices.cpp index 85e2c645d..7e999fe25 100644 --- a/src/cc/prices.cpp +++ b/src/cc/prices.cpp @@ -19,11 +19,39 @@ /* CBOPRET creates trustless oracles, which can be used for making a synthetic cash settlement system based on real world prices; - - 0.5% fee based on betamount, NOT leveraged betamount!! 0.1% collected by price basis determinant 0.2% collected by rekt tx + + At the simplest, prices CC allows to make leveraged cash settled bets on long and short BTCUSD: + BTCUSD, 1 with positive leverage parameter up to 777 + BTCUSD, 1 with negative leverage parameter up to -777 + + These specific limits of 0.5%, 0.1%, 0.2%, 777 should be able to be changed based on #define + + Another configuration is to send the 0.4% (or 0.2%) fees to a fee collection address (this is not currently implemented, but would be needed for systems that dont use -ac_perc to collect a global override) + + The definition of the synthetic instrument that is being tracked is actually defined with a forth type of syntax and is quite flexible to allow unlimited combinations and weights, but that is an independent aspect and will be covered later. + + Let us discuss the simplest synthetic case of a long or short of BTCUSD (or any other direct pricepoint from the trustless oracle). If you look at the charts, you will see the blue line that is direct from the miners (and therefore cant be directly used). The orange line is the 51% correlated price that is deterministically random selected from the prior 24 hours. And finally the green line which is simply the average value from the priot 24 hours. + + We will assume that the orange and green prices are able to be deterministically calculated from the raw coinbase data (blue). The prices rpc is currently working reasonably well and appears to return deterministic prices, however for use in the prices CC, it is often needed to find just a single data point. To that effect there is the temporary function prices_syntheticprice, which uses a bruteforce and totally inefficient way to calculate the correlated and smoothed prices. This inefficient process will need to be changed to a permanent storage of correlated and smoothed prices for each trustless oracle that is updated each block. This will then allow to directly lookup each value for any of the trustless prices. Such speed will indeed be needed to scale up usage of a REKT chain. + + Since the mined prices can be manipulated by any miner, combined with the +/-1% tolerance, it would be possible for an external miner to obtain a large hashrate and skew the price +1%, then to -1% to create a 2% price difference, which under high leverage might be able to generate a large profit. + + To avoid this precisely controllable biasing, the 51% correlation of past day is used (orange), which makes the price jump around a lot. The green line that sums the prior day is needed to remove this jitter back to the average value. However, this creates a 1.5 day delay to the price movement of the smoothed price compared to the current price. What this means is that if we want to use the green line to settle prices automatically, a trivial way to make money is to bet in the direct that the mined prices are relative to the smoothed prices. Given 1.5 day head start, it wont be any mystery which direction the smoothed line will move in the next 24 hours. + + So this makes the smoothed price unusable for settling the bets with. However, we cant use the correlated price either, as it would also allow to make bets when the correlated price picked a significantly lower/higher price than the raw price. The solution is to have a floating basis for the costbasis of the bet. In order to allow finding the right costbasis, for long bets the maximum price between the correlated and smoothed price is needed over the first day after the bet. For short bets, the minimum price is needed. + + What this means is that the actual starting price for a bet wont be known for sure when the bet is made, but if the price is relatively stable, there wont be much of a change. If there is a lot of recent volatility, then the starting price will have a high variability. In order to calculate the costbasis, it currently requires many calculations to find the MAX (or MIN) for the first day. Even when this is made to be a lookup, it still requires to issue a transaction to change the state of a bet from a "starting" state to a "in effect" state and this state change is indicated by whether the bettx vout that contains the costbasis utxo is spent or not. + + Once a bet goes into effect, then block by block, it is checked by the decentralized set of rekt scanners if it is rekt or not, in this case for double the reward for calculating the cost basis. This fully decentralized mechanism ensures that some node will decide to collect the free money and ensures that the bankroll is growing. To miss a rekt bet and not close it out when it can be is to allow it to survive for another block, which can change it profitability from negative to positive. + + Which comes to how profits are calculated. Once the costbasis is locked, then the profit calculation can be made based on the ratio between the costbasis and the current price, multiplied by the leverage. So, if a long position gains 10% at a 10x leverage, then approximately the entire bet amount will be made, ie. a double. Similarily with a short position, a 10% drop in price at 10x leverage will double the bet amount. Since it takes a full day to establish the costbasis, it is not possible to allow changing the costbasis for an existing bet, however it is possible to add funds so that it is less likely to be rekt. The sum of the initial bet and all added funds must be greater than the loss at every block to prevent a position from being rekt. To make it simple to calculate the amount of funds added, another bettx vout is used as a baton. Techniques similar to rogue CC to find where the bettx vout was spent and looking at each such transaction to find the total funds added can be used. + + The once that makes the bet is able to add funds or cashout at any block, as long as it isnt rekt. If it is rekt, the bettor is able to collect the rekt fee, so at least that is some consolation, but it is advised to increase the total funding to avoid being rekt. On a cashout all the funds that were bet adjusted by the profits can be collected. + + Hopefully the above description makes it clear what the following rpc calls should be doing: UniValue PricesBet(uint64_t txfee,int64_t amount,int16_t leverage,std::vector synthetic) funds are locked into 1of2 global CC address @@ -52,6 +80,9 @@ CBOPRET creates trustless oracles, which can be used for making a synthetic cash UniValue PricesList() a list of all pending and completed bets in different lists + + Appendix Synthetic position definition language: + */ // start of consensus code From ed6a0ade4400bf502b241e11477a50b02e202573 Mon Sep 17 00:00:00 2001 From: jl777 Date: Sat, 6 Apr 2019 02:40:49 -1100 Subject: [PATCH 03/35] Synthetic definition language --- src/cc/prices.cpp | 53 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/src/cc/prices.cpp b/src/cc/prices.cpp index 7e999fe25..6e95af3af 100644 --- a/src/cc/prices.cpp +++ b/src/cc/prices.cpp @@ -83,7 +83,58 @@ CBOPRET creates trustless oracles, which can be used for making a synthetic cash Appendix Synthetic position definition language: -*/ + Let us start from the familiar BTCUSD nomenclature. this is similar (identical) to forex EURUSD and the equivalent. Notice the price needs two things as it is actually a ratio, ie. BTCUSD is how many USD does 1 BTC get converted to. It can be thought of as the value of BTC/USD, in other words a ratio. + + The value of BTC alone, or USD alone, it is actually quite an abstract issue and it can only be approximated. Specific ways of how to do this can be discussed later, for now it is only important to understand that all prices are actually ratios. + + And these ratios work as normal algebra does. So a/b * b/c == a/c! You can try this out with BTCUSD and USDJPY -> BTC/USD * USD/JPY -> BTC/JPY or the BTCJPY price + + division is the reciprocal, so BTCUSD reciprocated is USDBTC + + Without getting into all the possible combinations of things, let us first understand what the language allows. It uses a stack based language, where individual tokens update the state. The final state needs to have an empty stack and it will have a calculated price. + + The most important is pushing a specific price onto the stack. All the correlated and smoothed prices are normalized so it has each integer unit equal to 0.00000001, amounts above 100 million are above one, amounts less are below one. 100 million is the unit constant. + + In the prices CC synthetic definition language, the symbol that is returned pushes the adjusted price to the stack. The adjustment is selecting between the correlated and smoothed if within a day from the bet creation, or just the smoothed if after a day. You can have a maximum depth of 3, any more than that and it should return an error. + + This means there are operations that are possible on 1, 2 and 3 symbols. For 1 symbol, it is easy, the only direct operation is the inverse, which is represented by "!". All items in the language are separated by "," + + "BTCUSD, !" + + The above is the inverse or USD/BTC, which is another way to short BTCUSD. It is also possible to short the entire synthetic with a negative leverage. The exact results of a -1 leverage and inverse, might not be exact due to the math involved with calculating the profit, but it should generally be similar. + + For two symbols, there is a bit more we can do, namely multiply and divide, combined with inverting, however to simplify the language any inverting is required to be done by the ordering of the symbols and usage of multiply or divide. multiply is "*" and divide is "/" the top of the stack (last to be pushed) is the divisor, the one right before the divisor is the numerator. + + "BTCUSD, USDJPY, *" <- That will create a BTCJPY synthetic + + "BTCEUR, BTCUSD, /" <- That will create a USDEUR synthetic + + If you experiment around with this, you will see that given two symbols and the proper order and * or /, you can always create the synthetic that you want, assuming what you want is the cancelling out of the term in common with the two symbols and the resulting ratio is between the two unique terms. + */ + +// Now we get to the three symbol operations, which there are 4 of *//, **/, *** and /// + +/* + these four operators work on the top of the stack in left to right order as the syntax of the definition lists it, though it is even possible to have the value from an earlier computation on the top of the stack. Ultimately all three will be multiplied together, so a * in a spot means it us used without changing. A / means its inverse will be used. + + "KMDBTC, BTCUSD, USDJPY, ***" <- this would create a KMDJPY synthetic. The various location of the / to make an inverse is to orient the raw symbol into the right orientation as the pricefeed is only getting one orientation of the ratio. + + So now we have covered all ways to map 1, 2 and 3 values on the top of the stack. A value can be on the top of the stack directly from a symbol, or as the result of some 1, 2 or 3 symbol operation. With a maximum stack depth of 3, it might require some experimentation to get a very complex synthetic to compile. Alternately, a stack deeper than 3 might be the acceptable solution if there are a family of synthetics that need it. + + At this point, it is time to describe the weights. It turns out that all above examples are incomplete and the synthetic descriptions are all insufficient and should generate an error. The reason is that the actual synthetic price is the value of the accumulator, which adds up all the weighted prices. In order to assign a weight to a price value on the stack, you simply use a number that is less than 2048. + + What such a weight number does, is consume the top of the stack, which also must be at depth of 1 and adds it to the accumulator. This allows combining multiple different synthetics into a meta synthetic, like for an aggregated index that is weighted by marketcap, or whatever other type of ratio trade that is desired. + + "BTCUSD, 1000, ETHBTC, BTCUSD, *, 300" -> that creates a dual index of BTCUSD and ETHUSD with a 30% ETH weight + + all weight operations consumes the one and only stack element and adds its weight to the accumulator, using this a very large number of terms can be all added together. Using inverses, allows to get the short direction into the equation mixed with longs, but all terms must be positive. If you want to create a spread between two synthetics, you need to create two different synthetics and go long with one and short with another. + + "BTCUSD, 1" with leverage -2 and "KMDBTC, BTCUSD, *, 1" with leverage 1 this will setup a +KMDUSD -2 BTCUSD spread when the two are combined, and would be at breakeven when KMDUSD gains 2x more percentage wise than BTC does. anytime KMD gains more, will be positive, if the gains are less, would be negative. + + Believe it or not, the string to binary compiler for synthetic description and interpretation of it is less than 200 lines of code. + + */ + // start of consensus code From dae0476a0adc89ca8c0ffca8412866af55a4cbee Mon Sep 17 00:00:00 2001 From: jl777 Date: Sat, 6 Apr 2019 06:49:05 -1100 Subject: [PATCH 04/35] More docs --- src/cc/pegs.cpp | 10 ---------- src/cc/prices.cpp | 5 +++++ 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/cc/pegs.cpp b/src/cc/pegs.cpp index dba9fc818..341e34c58 100644 --- a/src/cc/pegs.cpp +++ b/src/cc/pegs.cpp @@ -16,17 +16,7 @@ #include "CCPegs.h" /* - Pegs CC builds on top of CCOPRET modes which will create pricefeeds in the coinbase. - - flag&1: BTC/USD 4966.1400, BTC/GBP 3770.0402, BTC/EUR 4416.8452 GBPUSD 1.317264, EURUSD 1.124364 EURGBP 0.853560 - flag&2: (BGN 1.7462) (NZD 1.4771) (ILS 3.6258) (RUB 65.3700) (CAD 1.3320) (PHP 52.4160) (CHF 0.9995) (AUD 1.4122) (JPY 111.3660) (TRY 5.5483) (HKD 7.8498) (MYR 4.0816) (HRK 6.6337) (CZK 22.9937) (IDR 14220.0000) (DKK 6.6648) (NOK 8.6111) (HUF 287.2142) (GBP 0.7678) (MXN 19.1046) (THB 31.7500) (ISK 122.4107) (ZAR 14.1300) (BRL 3.8604) (SGD 1.3551) (PLN 3.8350) (INR 68.7531) (KRW 1136.3839) (RON 4.2516) (CNY 6.7200) (SEK 9.3230) (EUR 0.8928) (2019-04-02) -flag&4: (KMD 0.00025110) (ETH 0.03357500) (LTC 0.01642400) (BCHABC 0.05167400) (XMR 0.01398800) (IOTA 0.00007217) (DASH 0.02552600) (XEM 0.00001459) (ZEC 0.01440500) (WAVES 0.00062170) (RVN 0.00001215) (LSK 0.00041130) (DCR 0.00496000) (BTS 0.00001444) (ICX 0.00008750) (HOT 0.00000027) (STEEM 0.00010070) (ENJ 0.00003221) (STRAT 0.00022790) errs.0 - Funds deposited into CC address for a specific peg would then be used to fund the bid/ask as the pricefeed changes the price. Profits/losses would accumulate in the associated address. - - In the event funds exceed a specified level, it can be spent into a collection address. The idea is that the collection address can further be used for revshares. - - */ diff --git a/src/cc/prices.cpp b/src/cc/prices.cpp index 6e95af3af..ce257d33f 100644 --- a/src/cc/prices.cpp +++ b/src/cc/prices.cpp @@ -133,6 +133,11 @@ CBOPRET creates trustless oracles, which can be used for making a synthetic cash Believe it or not, the string to binary compiler for synthetic description and interpretation of it is less than 200 lines of code. + todo: complete all the above, bet tokens, cross chain prices within cluster These specific limits of 0.5%, 0.1%, 0.2%, 777 should be able to be changed based on #define + + Another configuration is to send the 0.4% (or 0.2%) fees to a fee collection scriptPubKey (this is not currently implemented, but would be needed for systems that dont use -ac_perc to collect a global override) this requires adding new vouts + + Modification: in the event there is one price in the accumulator and one price on the stack at the end, then it is a (A - B) spread */ From 6db2c41b518397d2ff948fd5a0cc9fa9e858c2ce Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Sun, 7 Apr 2019 21:57:17 +0800 Subject: [PATCH 05/35] inital commit for getSnapshot2 changes --- src/main.cpp | 114 +++++++++++----------------- src/rpc/misc.cpp | 5 +- src/txdb.cpp | 192 +++++++++++++---------------------------------- src/txdb.h | 2 +- 4 files changed, 98 insertions(+), 215 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index e8fe3810c..8fbc0f1dd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2967,6 +2967,33 @@ void DisconnectNotarisations(const CBlock &block) } } +int8_t GetAddressType(const CScript &scriptPubKey, CTxDestination &vDest, txnouttype &txType, vector> &vSols) +{ + int8_t keyType = 0; + // some non-standard types, like time lock coinbases, don't solve, but do extract + if ( (Solver(scriptPubKey, txType, vSols) || ExtractDestination(scriptPubKey, vDest)) ) + { + keyType = 1; + if (vDest.which()) + { + // if we failed to solve, and got a vDest, assume P2PKH or P2PK address returned + CKeyID kid; + if (CBitcoinAddress(vDest).GetKeyID(kid)) + { + vSols.push_back(vector(kid.begin(), kid.end())); + } + } + else if (txType == TX_SCRIPTHASH) + { + keyType = 2; + } + else if (txType == TX_CRYPTOCONDITION ) + { + keyType = 3; + } + } + return keyType; +} bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool* pfClean) { @@ -3002,20 +3029,9 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex vector> vSols; CTxDestination vDest; txnouttype txType = TX_PUBKEYHASH; - int keyType = 1; - if ((Solver(out.scriptPubKey, txType, vSols) || ExtractDestination(out.scriptPubKey, vDest)) && txType != TX_MULTISIG) { - if (vDest.which()) - { - CKeyID kid; - if (CBitcoinAddress(vDest).GetKeyID(kid)) - { - vSols.push_back(vector(kid.begin(), kid.end())); - } - } - else if (txType == TX_SCRIPTHASH) - { - keyType = 2; - } + int keyType = GetAddressType(out.scriptPubKey, vDest, txType, vSols); + if ( keyType != 0 ) + { for (auto addr : vSols) { uint160 addrHash = addr.size() == 20 ? uint160(addr) : Hash160(addr); @@ -3072,23 +3088,9 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex vector> vSols; CTxDestination vDest; txnouttype txType = TX_PUBKEYHASH; - int keyType = 1; - // some non-standard types, like time lock coinbases, don't solve, but do extract - if ((Solver(prevout.scriptPubKey, txType, vSols) || ExtractDestination(prevout.scriptPubKey, vDest))) + int keyType = GetAddressType(prevout.scriptPubKey, vDest, txType, vSols); + if ( keyType != 0 ) { - // if we failed to solve, and got a vDest, assume P2PKH or P2PK address returned - if (vDest.which()) - { - CKeyID kid; - if (CBitcoinAddress(vDest).GetKeyID(kid)) - { - vSols.push_back(vector(kid.begin(), kid.end())); - } - } - else if (txType == TX_SCRIPTHASH) - { - keyType = 2; - } for (auto addr : vSols) { uint160 addrHash = addr.size() == 20 ? uint160(addr) : Hash160(addr); @@ -3448,8 +3450,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (fAddressIndex || fSpentIndex) { - for (size_t j = 0; j < tx.vin.size(); j++) { - + for (size_t j = 0; j < tx.vin.size(); j++) + { const CTxIn input = tx.vin[j]; const CTxOut &prevout = view.GetOutputFor(tx.vin[j]); @@ -3457,25 +3459,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin CTxDestination vDest; txnouttype txType = TX_PUBKEYHASH; uint160 addrHash; - int keyType = 0; - // some non-standard types, like time lock coinbases, don't solve, but do extract - if ((Solver(prevout.scriptPubKey, txType, vSols) || ExtractDestination(prevout.scriptPubKey, vDest))) + int keyType = GetAddressType(prevout.scriptPubKey, vDest, txType, vSols); + if ( keyType != 0 ) { - keyType = 1; - - // if we failed to solve, and got a vDest, assume P2PKH or P2PK address returned - if (vDest.which()) - { - CKeyID kid; - if (CBitcoinAddress(vDest).GetKeyID(kid)) - { - vSols.push_back(vector(kid.begin(), kid.end())); - } - } - else if (txType == TX_SCRIPTHASH) - { - keyType = 2; - } for (auto addr : vSols) { addrHash = addr.size() == 20 ? uint160(addr) : Hash160(addr); @@ -3485,12 +3471,12 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // remove address from unspent index addressUnspentIndex.push_back(make_pair(CAddressUnspentKey(keyType, addrHash, input.prevout.hash, input.prevout.n), CAddressUnspentValue())); } - } - if (fSpentIndex) { - // add the spent index to determine the txid and input that spent an output - // and to find the amount and address from an input - spentIndex.push_back(make_pair(CSpentIndexKey(input.prevout.hash, input.prevout.n), CSpentIndexValue(txhash, j, pindex->GetHeight(), prevout.nValue, keyType, addrHash))); + if (fSpentIndex) { + // add the spent index to determine the txid and input that spent an output + // and to find the amount and address from an input + spentIndex.push_back(make_pair(CSpentIndexKey(input.prevout.hash, input.prevout.n), CSpentIndexValue(txhash, j, pindex->GetHeight(), prevout.nValue, keyType, addrHash))); + } } } } @@ -3541,23 +3527,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin vector> vSols; CTxDestination vDest; txnouttype txType = TX_PUBKEYHASH; - int keyType = 1; - // some non-standard types, like time lock coinbases, don't solve, but do extract - if ((Solver(out.scriptPubKey, txType, vSols) || ExtractDestination(out.scriptPubKey, vDest)) && txType != TX_MULTISIG) + int keyType = GetAddressType(out.scriptPubKey, vDest, txType, vSols); + if ( keyType != 0 ) { - // if we failed to solve, and got a vDest, assume P2PKH or P2PK address returned - if (vDest.which()) - { - CKeyID kid; - if (CBitcoinAddress(vDest).GetKeyID(kid)) - { - vSols.push_back(vector(kid.begin(), kid.end())); - } - } - else if (txType == TX_SCRIPTHASH) - { - keyType = 2; - } for (auto addr : vSols) { addrHash = addr.size() == 20 ? uint160(addr) : Hash160(addr); diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 814f7b9b8..cf7c85417 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -853,8 +853,9 @@ bool getAddressFromIndex(const int &type, const uint160 &hash, std::string &addr address = CBitcoinAddress(CScriptID(hash)).ToString(); } else if (type == 1) { address = CBitcoinAddress(CKeyID(hash)).ToString(); - } - else { + } else if (type == 3) { + address = CBitcoinAddress(CKeyID(hash)).ToString(); + } else { return false; } return true; diff --git a/src/txdb.cpp b/src/txdb.cpp index ace04ebdb..c8721c92a 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -458,10 +458,10 @@ uint32_t komodo_segid32(char *coinaddr); {"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPVMY", 1} \ }; -int32_t CBlockTreeDB::Snapshot2(int64_t dustthreshold,int32_t top,std::vector > &vaddr) +int32_t CBlockTreeDB::Snapshot2(int64_t dustthreshold, int32_t top, bool fRPC ,std::vector > &vaddr, UniValue &ret) { int64_t total = 0; int64_t totalAddresses = 0; std::string address; - int64_t utxos = 0; int64_t ignoredAddresses = 0; + int64_t utxos = 0; int64_t ignoredAddresses = 0, cryptoConditionsUTXOs = 0, cryptoConditionsTotals = 0; DECLARE_IGNORELIST boost::scoped_ptr iter(NewIterator()); std::map addressAmounts; @@ -482,6 +482,12 @@ int32_t CBlockTreeDB::Snapshot2(int64_t dustthreshold,int32_t top,std::vector GetValue(nValue); getAddressFromIndex(indexKey.type, indexKey.hashBytes, address); + if ( indexKey.type == 3 ) + { + cryptoConditionsUTXOs++; + cryptoConditionsTotals += nValue; + continue; + } if ( nValue > dustthreshold ) { std::map ::iterator ignored = ignoredMap.find(address); @@ -508,7 +514,7 @@ int32_t CBlockTreeDB::Snapshot2(int64_t dustthreshold,int32_t top,std::vector element : addressAmounts) vaddr.push_back( make_pair(element.second, element.first) ); std::sort(vaddr.rbegin(), vaddr.rend()); int topN = 0; for (std::vector>::iterator it = vaddr.begin(); it!=vaddr.end(); ++it) { - //obj.push_back( make_pair("addr", it->second.c_str() ) ); - //char amount[32]; - //sprintf(amount, "%.8f", (double) it->first / COIN); - //obj.push_back( make_pair("amount", amount) ); - //obj.push_back( make_pair("segid",(int32_t)komodo_segid32((char *)it->second.c_str()) & 0x3f) ); - //addressesSorted.push_back(obj); total += it->first; topN++; // If requested, only show top N addresses in output JSON if ( top == topN ) break; } + // this is for the snapshot RPC, you can skip this by passing false to the 3rd arugment. + // Still needs UniValue defined to use SnapShot2 though, can this be changed to just pass 0? + // I tried to make it a pointer, and check if the pointer was 0, but UniValue class didnt like that. + if ( fRPC ) + { + // Total amount in this snapshot, which is less than circulating supply if top parameter is used + ret.push_back(make_pair("total", (double) total / COIN )); + // Average amount in each address of this snapshot + ret.push_back(make_pair("average",(double) (total/COIN) / totalAddresses )); + // Total number of utxos processed in this snaphot + ret.push_back(make_pair("utxos", utxos)); + // Total number of addresses in this snaphot + ret.push_back(make_pair("total_addresses", top ? top : totalAddresses )); + // Total number of ignored addresses in this snaphot + ret.push_back(make_pair("ignored_addresses", ignoredAddresses)); + // Total number of crypto condition utxos we skipped + ret.push_back(make_pair("skipped_cc_utxos", cryptoConditionsUTXOs)); + // Total value of skipped crypto condition utxos + ret.push_back(make_pair("cc_utxo_value", (double) cryptoConditionsTotals / COIN)); + // The snapshot finished at this block height + ret.push_back(make_pair("ending_height", chainActive.Height())); + } return(topN); } UniValue CBlockTreeDB::Snapshot(int top) { - int64_t total = 0; int64_t totalAddresses = 0; std::string address; - int64_t utxos = 0; int64_t ignoredAddresses = 0; - DECLARE_IGNORELIST - boost::scoped_ptr iter(NewIterator()); - std::map addressAmounts; + int topN = 0; std::vector > vaddr; UniValue result(UniValue::VOBJ); - result.push_back(Pair("start_time", (int) time(NULL))); - - /* std::map ignoredMap = { - {"RReUxSs5hGE39ELU23DfydX8riUuzdrHAE", 1}, - {"RMUF3UDmzWFLSKV82iFbMaqzJpUnrWjcT4", 1}, - {"RA5imhVyJa7yHhggmBytWuDr923j2P1bxx", 1}, - {"RBM5LofZFodMeewUzoMWcxedm3L3hYRaWg", 1}, - {"RAdcko2d94TQUcJhtFHZZjMyWBKEVfgn4J", 1}, - {"RLzUaZ934k2EFCsAiVjrJqM8uU1vmMRFzk", 1}, - {"RMSZMWZXv4FhUgWhEo4R3AQXmRDJ6rsGyt", 1}, - {"RUDrX1v5toCsJMUgtvBmScKjwCB5NaR8py", 1}, - {"RMSZMWZXv4FhUgWhEo4R3AQXmRDJ6rsGyt", 1}, - {"RRvwmbkxR5YRzPGL5kMFHMe1AH33MeD8rN", 1}, - {"RQLQvSgpPAJNPgnpc8MrYsbBhep95nCS8L", 1}, - {"RK8JtBV78HdvEPvtV5ckeMPSTojZPzHUTe", 1}, - {"RHVs2KaCTGUMNv3cyWiG1jkEvZjigbCnD2", 1}, - {"RE3SVaDgdjkRPYA6TRobbthsfCmxQedVgF", 1}, - {"RW6S5Lw5ZCCvDyq4QV9vVy7jDHfnynr5mn", 1}, - {"RTkJwAYtdXXhVsS3JXBAJPnKaBfMDEswF8", 1}, - {"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPVMY", 1} //Burnaddress for null privkey - };*/ - - int64_t startingHeight = chainActive.Height(); - //fprintf(stderr, "Starting snapshot at height %lli\n", startingHeight); - for (iter->SeekToLast(); iter->Valid(); iter->Prev()) - { - boost::this_thread::interruption_point(); - try - { - std::vector slKey = std::vector(); - pair keyObj; - iter->GetKey(keyObj); - - char chType = keyObj.first; - CAddressIndexIteratorKey indexKey = keyObj.second; - - //fprintf(stderr, "chType=%d\n", chType); - if (chType == DB_ADDRESSUNSPENTINDEX) - { - try { - CAmount nValue; - iter->GetValue(nValue); - - getAddressFromIndex(indexKey.type, indexKey.hashBytes, address); - - if (nValue > 0) { - std::map ::iterator ignored = ignoredMap.find(address); - if (ignored != ignoredMap.end()) { - fprintf(stderr,"ignoring %s\n", address.c_str()); - ignoredAddresses++; - continue; - } - - std::map ::iterator pos = addressAmounts.find(address); - if (pos == addressAmounts.end()) { - // insert new address + utxo amount - //fprintf(stderr, "inserting new address %s with amount %li\n", address.c_str(), nValue); - addressAmounts[address] = nValue; - totalAddresses++; - } else { - // update unspent tally for this address - //fprintf(stderr, "updating address %s with new utxo amount %li\n", address.c_str(), nValue); - addressAmounts[address] += nValue; - } - //fprintf(stderr,"{\"%s\", %.8f},\n",address.c_str(),(double)nValue/COIN); - // total += nValue; - utxos++; - } else { - fprintf(stderr,"ignoring amount=0 UTXO for %s\n", address.c_str()); - } - } catch (const std::exception& e) { - fprintf(stderr, "DONE %s: LevelDB addressindex exception! - %s\n", __func__, e.what()); - break; - } - } - } catch (const std::exception& e) { - fprintf(stderr, "DONE reading index entries\n"); - break; - } - } - - UniValue addresses(UniValue::VARR); - //fprintf(stderr, "total=%f, totalAddresses=%li, utxos=%li, ignored=%li\n", (double) total / COIN, totalAddresses, utxos, ignoredAddresses); - - for (std::pair element : addressAmounts) { - vaddr.push_back( make_pair(element.second, element.first) ); - } - std::sort(vaddr.rbegin(), vaddr.rend()); - - UniValue obj(UniValue::VOBJ); UniValue addressesSorted(UniValue::VARR); - int topN = 0; - for (std::vector>::iterator it = vaddr.begin(); it!=vaddr.end(); ++it) + result.push_back(Pair("start_time", (int) time(NULL))); + if ( Snapshot2(0,top,true,vaddr,result) != 0 ) { - UniValue obj(UniValue::VOBJ); - obj.push_back( make_pair("addr", it->second.c_str() ) ); - char amount[32]; - sprintf(amount, "%.8f", (double) it->first / COIN); - obj.push_back( make_pair("amount", amount) ); - obj.push_back( make_pair("segid",(int32_t)komodo_segid32((char *)it->second.c_str()) & 0x3f) ); - total += it->first; - addressesSorted.push_back(obj); - topN++; - // If requested, only show top N addresses in output JSON - if (top == topN) - break; - } - - if (top) - totalAddresses = top; - - if (totalAddresses > 0) { - // Array of all addreses with balances + for (std::vector>::iterator it = vaddr.begin(); it!=vaddr.end(); ++it) + { + UniValue obj(UniValue::VOBJ); + obj.push_back( make_pair("addr", it->second.c_str() ) ); + char amount[32]; + sprintf(amount, "%.8f", (double) it->first / COIN); + obj.push_back( make_pair("amount", amount) ); + obj.push_back( make_pair("segid",(int32_t)komodo_segid32((char *)it->second.c_str()) & 0x3f) ); + addressesSorted.push_back(obj); + topN++; + // If requested, only show top N addresses in output JSON + if ( top == topN ) + break; + } + // Array of all addreses with balances result.push_back(make_pair("addresses", addressesSorted)); - // Total amount in this snapshot, which is less than circulating supply if top parameter is used - result.push_back(make_pair("total", (double) total / COIN )); - // Average amount in each address of this snapshot - result.push_back(make_pair("average",(double) (total/COIN) / totalAddresses )); - } - // Total number of utxos processed in this snaphot - result.push_back(make_pair("utxos", utxos)); - // Total number of addresses in this snaphot - result.push_back(make_pair("total_addresses", totalAddresses)); - // Total number of ignored addresses in this snaphot - result.push_back(make_pair("ignored_addresses", ignoredAddresses)); - // The snapshot began at this block height - result.push_back(make_pair("start_height", startingHeight)); - // The snapshot finished at this block height - result.push_back(make_pair("ending_height", chainActive.Height())); + } else result.push_back(make_pair("error", "problem doing snapshot")); return(result); } diff --git a/src/txdb.h b/src/txdb.h index 9b80b922b..8b98994a2 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -116,7 +116,7 @@ public: bool LoadBlockIndexGuts(); bool blockOnchainActive(const uint256 &hash); UniValue Snapshot(int top); - int32_t Snapshot2(int64_t dustthreshold,int32_t top,std::vector > &vaddr); + int32_t Snapshot2(int64_t dustthreshold, int32_t top, bool fRPC ,std::vector > &vaddr, UniValue &ret); }; #endif // BITCOIN_TXDB_H From df118e7c8ff255a3fa3ecf4d14b6e0b8ba9fff62 Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Sun, 7 Apr 2019 23:16:25 +0800 Subject: [PATCH 06/35] fix json output --- src/txdb.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/txdb.cpp b/src/txdb.cpp index c8721c92a..e5c260e4f 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -548,7 +548,7 @@ int32_t CBlockTreeDB::Snapshot2(int64_t dustthreshold, int32_t top, bool fRPC ,s if ( fRPC ) { // Total amount in this snapshot, which is less than circulating supply if top parameter is used - ret.push_back(make_pair("total", (double) total / COIN )); + ret.push_back(make_pair("total", (double) (total+cryptoConditionsTotals)/ COIN )); // Average amount in each address of this snapshot ret.push_back(make_pair("average",(double) (total/COIN) / totalAddresses )); // Total number of utxos processed in this snaphot @@ -561,6 +561,8 @@ int32_t CBlockTreeDB::Snapshot2(int64_t dustthreshold, int32_t top, bool fRPC ,s ret.push_back(make_pair("skipped_cc_utxos", cryptoConditionsUTXOs)); // Total value of skipped crypto condition utxos ret.push_back(make_pair("cc_utxo_value", (double) cryptoConditionsTotals / COIN)); + // total of all the address's, does not count coins in CC vouts. + ret.push_back(make_pair("address_total", (double) total/ COIN )); // The snapshot finished at this block height ret.push_back(make_pair("ending_height", chainActive.Height())); } From 7c86c40d7153ae22b7278de4b88e38db5128b350 Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Sun, 7 Apr 2019 23:54:44 +0800 Subject: [PATCH 07/35] description comment --- src/txdb.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/txdb.cpp b/src/txdb.cpp index e5c260e4f..93000d9fb 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -548,6 +548,7 @@ int32_t CBlockTreeDB::Snapshot2(int64_t dustthreshold, int32_t top, bool fRPC ,s if ( fRPC ) { // Total amount in this snapshot, which is less than circulating supply if top parameter is used + // Use the address_total for a total of all address included when using top parameter. ret.push_back(make_pair("total", (double) (total+cryptoConditionsTotals)/ COIN )); // Average amount in each address of this snapshot ret.push_back(make_pair("average",(double) (total/COIN) / totalAddresses )); From 247a2ccc7f7a03e5ea7e91c45da8d5eb5d9986a6 Mon Sep 17 00:00:00 2001 From: jl777 Date: Sun, 7 Apr 2019 06:15:43 -1100 Subject: [PATCH 08/35] Sync --- src/cc/pegs.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cc/pegs.cpp b/src/cc/pegs.cpp index 341e34c58..0c9613df3 100644 --- a/src/cc/pegs.cpp +++ b/src/cc/pegs.cpp @@ -17,8 +17,7 @@ /* - -*/ + */ // start of consensus code From 07f9635bd0e2ea46208bb4c8cb1f12d43611c39f Mon Sep 17 00:00:00 2001 From: jl777 Date: Mon, 8 Apr 2019 02:41:05 -1100 Subject: [PATCH 09/35] Comments --- src/cc/pegs.cpp | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/cc/pegs.cpp b/src/cc/pegs.cpp index 0c9613df3..f6c9ae5b1 100644 --- a/src/cc/pegs.cpp +++ b/src/cc/pegs.cpp @@ -16,7 +16,52 @@ #include "CCPegs.h" /* +pegs CC is able to create a coin backed (by any supported coin with gateways CC deposits) and pegged to any synthetic price that is able to be calculated based on prices CC + + First, the prices CC needs to be understood, so the extensive comments at the top of ~/src/cc/prices.cpp needs to be understood. + + The second aspect is the ability to import coins, as used by the crosschain burn/import and the -ac_import chains. + + + + OK, now we are ready to describe the pegs CC. Let us imagine an -ac_import sidechain with KMD gateways CC. Now we have each native coin fungible with the real KMD via the gateways deposit/withdraw mechanism. Let us start with that and make a pegged and backed USD chain. + + + + Here the native coin is KMD, but we want USD, so there needs to be a way to convert the KMD amounts into USD amounts. Something like "KMDBTC, BTCUSD, *, 1" which is the prices CC syntax to calculate KMD/USD, which is exactly what we need. So now we can assume that we have a block by block usable KMD/USD price. implementationwise, there can be an -ac option like -ac_peg="KMDBTC, BTCUSD, *, 1" and in conjunction with -ac_import=KMD gateways CC sidechain, we now have a chain where deposit of KMD issues the correct USD coins and redeem of USD coins releases the correct number of KMD coins. + + Are we done yet? + + Not quite, as the prices of KMD will be quite volatile relative to USD, which is good during bull markets, not so happy during bear markets. There are 2 halves to this problem, how to deal with massive price increase (easy to solve), how to solve 90% price drop (a lot harder). + + In order to solve both, what is needed is an "account" based tracking which updates based on both price change, coins issued, payments made. So let us create an account that is based on a specific pubkey, where all relevant deposits, issuances, withdraws are tracked via appropriate vin/vout markers. + + Let us modify the USD chain above so that only 80% of the possible USD is issued and 20% held in reserve. This 80% should be at least some easily changeable #define, or even an -ac parameter. We want the issued coins to be released without any encumberances, but the residual 20% value is still controlled (owned) but the depositor. This account has the amount of KMD deposited and USD issued. At the moment of deposit, there will still be 20% equity left. Let us start with 1000 KMD deposit, $1.5 per KMD -> 800 KMD converted to 1200 USD into depositor pubkey and the account of (1000 KMD, -1200 USD) = 200 KMD or $300 equity. + + Now it becomes easy for the bull market case, which is to allow (for a fee like 1%) issuance of more USD as the equity increases, so let us imagine KMD at $10: + + (1000 KMD, -1200 USD, 200KMD reserve) -> $2000 equity, issue 80% -> $1600 using 160 KMD + (1000 KMD, -1200 USD, 200KMD reserve, -160KMD, issue $1600 USD, 40 KMD reserve) + + we have $2800 USD in circulation, 40 KMD reserve left against $10000 marketcap of the original deposit. It it easy to see that there are never any problems with lack of KMD to redeem the issued USD in a world where prices only go up. Total USD issuance can be limited by using a decentralized account tracking based on each deposit. + + What is evident though is that with the constantly changing price and the various times that all the various deposits issue USD, the global reserves are something that will be hard to predict and in fact needs to be specifically tracked. Let us combine all accounts exposure in to a global reserves factor. This factor will control various max/min/ allowed and fee percentages. + + Now we are prepared to handle the price goes down scenario. We can rely on the global equity/reserve ratio to be changing relatively slowly as the reference price is the smooted trustless oracles price. This means there will be enough blocks to adjust the global reserves percentage. What we need to do is liquidate specific positions that have the least reserves. + + What does liquidation mean? It means a specific account will be purchased at below its current value and the KMD withdrawn. Let us assume the price drops to $5: + + (1000 KMD, -1200 USD, 200KMD reserve, -160KMD, issue $1600 USD, 40 KMD reserve) 1000 KMD with 2800 USD issued so $2200 reserves. Let us assume it can be liquidated at a 10% discount, so for $2000 in addition to the $2800, the 5000 KMD is able to be withdrawn. This removes 4800 USD coins for 1000 KMD, which is a very low reserve amount of 4%. If a low reserve amount is removed from the system, then the global reserve amount must be improved. + + Now, we have a decentralized mechanism to handle the price going lower! Combined with the fully decentralized method new USD coins are issued, makes this argubably the first decentralized blockchain that is both backed and pegged. There is the reliance on the gateways CC multisig signers, so there is a fundamental federated trust for chains without intrinsic value. + + Also, notice that the flexibly syntax of prices CC allows to define pegs easily for virtually any type of synthetic, and all the ECB fiats can easily get a backed and pegged coin. + + Let us now consider how to enforce a peg onto a specific gateways CC token. If this can also be achieved, then a full DEX for all the different gateways CC supported coins can be created onto a single fiat denominated chain. + + + */ // start of consensus code From 74aa8a95364df9b26e18bbd961e0fdcfa5fd0fd6 Mon Sep 17 00:00:00 2001 From: jl777 Date: Mon, 8 Apr 2019 02:47:02 -1100 Subject: [PATCH 10/35] Update --- src/cc/pegs.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cc/pegs.cpp b/src/cc/pegs.cpp index f6c9ae5b1..218f4c68e 100644 --- a/src/cc/pegs.cpp +++ b/src/cc/pegs.cpp @@ -53,6 +53,9 @@ pegs CC is able to create a coin backed (by any supported coin with gateways CC (1000 KMD, -1200 USD, 200KMD reserve, -160KMD, issue $1600 USD, 40 KMD reserve) 1000 KMD with 2800 USD issued so $2200 reserves. Let us assume it can be liquidated at a 10% discount, so for $2000 in addition to the $2800, the 5000 KMD is able to be withdrawn. This removes 4800 USD coins for 1000 KMD, which is a very low reserve amount of 4%. If a low reserve amount is removed from the system, then the global reserve amount must be improved. + In addition to the global reserves calculation, there needs to be a trigger percentage that enables positions to be liquidated. We also want to liquidate the worst positions, so in addition to the trigger percentage, there should be a liquidation threshold, and the liquidator would need to find 3 or more better positions that are beyond the liquidation threshold, to be able to liquidate. This will get us to at most 3 accounts that could be liquidated but are not able to, so some method to allow those to also be liquidated. The liquidating nodes are making instant profits, so they should be expected to do whatever blockchain scanning and proving to make things easy for the rest of the nodes + + Now, we have a decentralized mechanism to handle the price going lower! Combined with the fully decentralized method new USD coins are issued, makes this argubably the first decentralized blockchain that is both backed and pegged. There is the reliance on the gateways CC multisig signers, so there is a fundamental federated trust for chains without intrinsic value. Also, notice that the flexibly syntax of prices CC allows to define pegs easily for virtually any type of synthetic, and all the ECB fiats can easily get a backed and pegged coin. From 01be71fd44280d2c23d348b775ddf697f5a27759 Mon Sep 17 00:00:00 2001 From: jl777 Date: Mon, 8 Apr 2019 05:29:47 -1100 Subject: [PATCH 11/35] Unsolved issue --- src/cc/pegs.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/cc/pegs.cpp b/src/cc/pegs.cpp index 218f4c68e..b83279276 100644 --- a/src/cc/pegs.cpp +++ b/src/cc/pegs.cpp @@ -53,8 +53,15 @@ pegs CC is able to create a coin backed (by any supported coin with gateways CC (1000 KMD, -1200 USD, 200KMD reserve, -160KMD, issue $1600 USD, 40 KMD reserve) 1000 KMD with 2800 USD issued so $2200 reserves. Let us assume it can be liquidated at a 10% discount, so for $2000 in addition to the $2800, the 5000 KMD is able to be withdrawn. This removes 4800 USD coins for 1000 KMD, which is a very low reserve amount of 4%. If a low reserve amount is removed from the system, then the global reserve amount must be improved. - In addition to the global reserves calculation, there needs to be a trigger percentage that enables positions to be liquidated. We also want to liquidate the worst positions, so in addition to the trigger percentage, there should be a liquidation threshold, and the liquidator would need to find 3 or more better positions that are beyond the liquidation threshold, to be able to liquidate. This will get us to at most 3 accounts that could be liquidated but are not able to, so some method to allow those to also be liquidated. The liquidating nodes are making instant profits, so they should be expected to do whatever blockchain scanning and proving to make things easy for the rest of the nodes + In addition to the global reserves calculation, there needs to be a trigger percentage that enables positions to be liquidated. We also want to liquidate the worst positions, so in addition to the trigger percentage, there should be a liquidation threshold, and the liquidator would need to find 3 or more better positions that are beyond the liquidation threshold, to be able to liquidate. This will get us to at most 3 accounts that could be liquidated but are not able to, so some method to allow those to also be liquidated. The liquidating nodes are making instant profits, so they should be expected to do whatever blockchain scanning and proving to make things easy for the rest of the nodes. + One last issue is the normal redemption case where we are not liquidating. In this case, it should be done at the current marketprice, should improve the global reserves metrics and not cause anybody whose position was modified to have cause for complaint. Ideally, there would be an account that has the identical to the global reserve percentage and also at the same price as current marketprice, but this is not realistic, so we need to identify classes of accounts and consider which ones can be fully or partially liquidated to satisfy the constraints. + + looking at our example account: + (1000 KMD, -1200 USD, 200KMD reserve, -160KMD, issue $1600 USD, 40 KMD reserve) + + what sort of non-liquidation withdraw would be acceptable? if the base amount 1000 KMD is reduced along with USD owed, then the reserve status will go up for the account. but that would seem to allow extra USD to be able to be issued. there should be no disadvantage from funding a withdraw, but also not any large advantage. it needs to be a neutral event.... + UNSOLVED selection, account adjustment issue Now, we have a decentralized mechanism to handle the price going lower! Combined with the fully decentralized method new USD coins are issued, makes this argubably the first decentralized blockchain that is both backed and pegged. There is the reliance on the gateways CC multisig signers, so there is a fundamental federated trust for chains without intrinsic value. From d8edaa38ecf3b9aa3be5470c89d1ec508bcc3380 Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Tue, 9 Apr 2019 01:36:30 +0800 Subject: [PATCH 12/35] make wallet filter work for testnet notary --- src/wallet/wallet.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 1208a77f2..003404c97 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1772,7 +1772,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl if (fExisted || IsMine(tx) || IsFromMe(tx) || sproutNoteData.size() > 0 || saplingNoteData.size() > 0) { // wallet filter for notary nodes. Disabled! Can be reenabled or customised for any specific use, pools could also use this to prevent wallet dwy attack. - if ( 0 && !tx.IsCoinBase() && !NOTARY_ADDRESS.empty() && IS_STAKED_NOTARY > -1 ) + if ( !tx.IsCoinBase() ) //&& !NOTARY_ADDRESS.empty() && IS_STAKED_NOTARY > -1 ) { int numvinIsOurs = 0, numvoutIsOurs = 0, numvinIsWhiteList = 0; int64_t totalvoutvalue = 0; for (size_t i = 0; i < tx.vin.size(); i++) @@ -1782,7 +1782,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl { if (ExtractDestination(txin.vout[tx.vin[i].prevout.n].scriptPubKey, address)) { - if ( CBitcoinAddress(address).ToString() == NOTARY_ADDRESS ) + if ( CBitcoinAddress(address).ToString() == "RXhapCShoqNeWytLXeWR2wX7m5xfNYfxNx" ) numvinIsOurs++; if ( !WHITELIST_ADDRESS.empty() ) { @@ -1803,6 +1803,11 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl // Count vouts, check if OUR notary address is the receiver. if ( numvinIsOurs == 0 && numvinIsWhiteList == 0 ) { + // if MIN_RECV_SATS is 0, we are on full lock down mode, accept NO transactions. + if ( 1 ) //MIN_RECV_SATS == 0 ) { + fprintf(stderr, "This node is on full lock down all txs are ignored! \n"); + return false; + } for (size_t i = 0; i < tx.vout.size() ; i++) { CTxDestination address2; @@ -1815,11 +1820,6 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl } } } - // if MIN_RECV_SATS is 0, we are on full lock down mode, accept NO transactions. - if ( MIN_RECV_SATS == 0 ) { - fprintf(stderr, "This node is on full lock down all txs are ignored! \n"); - return false; - } // If no vouts are to the notary address we will ignore them. if ( numvoutIsOurs == 0 ) { fprintf(stderr, "Received transaction to address other than notary address, ignored! \n"); From 7e74cb117ca964bf7a415656b2e622edc95d3599 Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Tue, 9 Apr 2019 01:39:38 +0800 Subject: [PATCH 13/35] fix --- src/wallet/wallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 003404c97..592a22c34 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1804,7 +1804,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl if ( numvinIsOurs == 0 && numvinIsWhiteList == 0 ) { // if MIN_RECV_SATS is 0, we are on full lock down mode, accept NO transactions. - if ( 1 ) //MIN_RECV_SATS == 0 ) { + if ( 1 ) { //MIN_RECV_SATS == 0 ) { fprintf(stderr, "This node is on full lock down all txs are ignored! \n"); return false; } From faea9232848f80892130f6f3d76cc0372560ed98 Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Tue, 9 Apr 2019 05:10:52 +0800 Subject: [PATCH 14/35] set notary address from -pubkey filter still default to on. --- src/wallet/wallet.cpp | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 592a22c34..c16720e60 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1751,6 +1751,8 @@ extern uint8_t NOTARY_PUBKEY33[33]; extern std::string NOTARY_ADDRESS,WHITELIST_ADDRESS; extern int32_t IS_STAKED_NOTARY; extern uint64_t MIN_RECV_SATS; +bool WALLET_FILTER = true; +#include "cc/CCinclude.h" bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate) { @@ -1769,41 +1771,41 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl return false; } } + static std::string NotaryAddress; static bool didinit; + if ( !didinit && NotaryAddress.empty() && NOTARY_PUBKEY33[0] != 0 ) + { + didinit = true; + char Raddress[64]; + pubkey2addr((char *)Raddress,(uint8_t *)NOTARY_PUBKEY33); + NotaryAddress.assign(Raddress); + } if (fExisted || IsMine(tx) || IsFromMe(tx) || sproutNoteData.size() > 0 || saplingNoteData.size() > 0) { // wallet filter for notary nodes. Disabled! Can be reenabled or customised for any specific use, pools could also use this to prevent wallet dwy attack. - if ( !tx.IsCoinBase() ) //&& !NOTARY_ADDRESS.empty() && IS_STAKED_NOTARY > -1 ) + if ( !tx.IsCoinBase() && WALLET_FILTER && !NotaryAddress.empty() ) //&& !NOTARY_ADDRESS.empty() && IS_STAKED_NOTARY > -1 ) { - int numvinIsOurs = 0, numvoutIsOurs = 0, numvinIsWhiteList = 0; int64_t totalvoutvalue = 0; + int numvinIsOurs = 0, numvinIsWhiteList = 0; // numvoutIsOurs = 0, int64_t totalvoutvalue = 0; for (size_t i = 0; i < tx.vin.size(); i++) { uint256 hash; CTransaction txin; CTxDestination address; - if (GetTransaction(tx.vin[i].prevout.hash,txin,hash,false)) + if ( GetTransaction(tx.vin[i].prevout.hash,txin,hash,false) && ExtractDestination(txin.vout[tx.vin[i].prevout.n].scriptPubKey, address) ) { - if (ExtractDestination(txin.vout[tx.vin[i].prevout.n].scriptPubKey, address)) - { - if ( CBitcoinAddress(address).ToString() == "RXhapCShoqNeWytLXeWR2wX7m5xfNYfxNx" ) - numvinIsOurs++; - if ( !WHITELIST_ADDRESS.empty() ) - { - //fprintf(stderr, "white list address: %s recv address: %s\n", WHITELIST_ADDRESS.c_str(),CBitcoinAddress(address).ToString().c_str()); - if ( CBitcoinAddress(address).ToString() == WHITELIST_ADDRESS ) { - //fprintf(stderr, "whitlisted is set to true here.\n"); - numvinIsWhiteList++; - } - } - } + if ( CBitcoinAddress(address).ToString() == NotaryAddress ) + numvinIsOurs++; + if ( !WHITELIST_ADDRESS.empty() && CBitcoinAddress(address).ToString() == WHITELIST_ADDRESS ) + numvinIsWhiteList++; } } // Now we know if it was a tx sent to us, that wasnt from ourself or the whitelist address if set.. if ( numvinIsOurs != 0 ) - fprintf(stderr, "We sent from address: %s vins: %d\n",NOTARY_ADDRESS.c_str(),numvinIsOurs); + fprintf(stderr, "We sent from address: %s vins: %d\n",NotaryAddress.c_str(),numvinIsOurs); if ( numvinIsWhiteList != 0 ) fprintf(stderr, "We received from whitelisted address: %s\n",WHITELIST_ADDRESS.c_str()); // Count vouts, check if OUR notary address is the receiver. if ( numvinIsOurs == 0 && numvinIsWhiteList == 0 ) { - // if MIN_RECV_SATS is 0, we are on full lock down mode, accept NO transactions. + return false; + /*/ if MIN_RECV_SATS is 0, we are on full lock down mode, accept NO transactions. if ( 1 ) { //MIN_RECV_SATS == 0 ) { fprintf(stderr, "This node is on full lock down all txs are ignored! \n"); return false; @@ -1832,7 +1834,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl // average vout size is less than set minimum, default is 1 coin, we will ignore it fprintf(stderr, "ignored: %d vouts average size of %ld sats.\n",numvoutIsOurs, (long)avgVoutSize); return false; - } + } */ } } From a30fb4ae364d3040e352dc154d197c3a6ba33c8f Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Tue, 9 Apr 2019 05:38:10 +0800 Subject: [PATCH 15/35] test --- src/wallet/wallet.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index c16720e60..ac6b7d6c0 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1778,6 +1778,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl char Raddress[64]; pubkey2addr((char *)Raddress,(uint8_t *)NOTARY_PUBKEY33); NotaryAddress.assign(Raddress); + fprintf(stderr, "1 notary address.%s\n", NotaryAddress.c_str()); } if (fExisted || IsMine(tx) || IsFromMe(tx) || sproutNoteData.size() > 0 || saplingNoteData.size() > 0) { @@ -1790,12 +1791,14 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl uint256 hash; CTransaction txin; CTxDestination address; if ( GetTransaction(tx.vin[i].prevout.hash,txin,hash,false) && ExtractDestination(txin.vout[tx.vin[i].prevout.n].scriptPubKey, address) ) { + fprintf(stderr, "2 notary address.%s address.%s\n", NotaryAddress.c_str(), address.c_str()); if ( CBitcoinAddress(address).ToString() == NotaryAddress ) numvinIsOurs++; if ( !WHITELIST_ADDRESS.empty() && CBitcoinAddress(address).ToString() == WHITELIST_ADDRESS ) numvinIsWhiteList++; } } + fprintf(stderr, "3 notary address.%s\n", NotaryAddress.c_str()); // Now we know if it was a tx sent to us, that wasnt from ourself or the whitelist address if set.. if ( numvinIsOurs != 0 ) fprintf(stderr, "We sent from address: %s vins: %d\n",NotaryAddress.c_str(),numvinIsOurs); From 0d587ccc31697e1a758d27e9bd4da10aa3093a60 Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Tue, 9 Apr 2019 05:39:34 +0800 Subject: [PATCH 16/35] fix --- src/wallet/wallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index ac6b7d6c0..279b149e8 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1791,7 +1791,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl uint256 hash; CTransaction txin; CTxDestination address; if ( GetTransaction(tx.vin[i].prevout.hash,txin,hash,false) && ExtractDestination(txin.vout[tx.vin[i].prevout.n].scriptPubKey, address) ) { - fprintf(stderr, "2 notary address.%s address.%s\n", NotaryAddress.c_str(), address.c_str()); + fprintf(stderr, "2 notary address.%s address.%s\n", NotaryAddress.c_str(), CBitcoinAddress(address).ToString().c_str()); if ( CBitcoinAddress(address).ToString() == NotaryAddress ) numvinIsOurs++; if ( !WHITELIST_ADDRESS.empty() && CBitcoinAddress(address).ToString() == WHITELIST_ADDRESS ) From 6f5e339884dcee6c825c59de2aa339e2db2be1cb Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Tue, 9 Apr 2019 05:50:06 +0800 Subject: [PATCH 17/35] fix --- src/wallet/wallet.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 279b149e8..f4a52cf24 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1778,7 +1778,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl char Raddress[64]; pubkey2addr((char *)Raddress,(uint8_t *)NOTARY_PUBKEY33); NotaryAddress.assign(Raddress); - fprintf(stderr, "1 notary address.%s\n", NotaryAddress.c_str()); + fprintf(stderr, "notary address set to %s\n", NotaryAddress.c_str()); } if (fExisted || IsMine(tx) || IsFromMe(tx) || sproutNoteData.size() > 0 || saplingNoteData.size() > 0) { @@ -1791,14 +1791,12 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl uint256 hash; CTransaction txin; CTxDestination address; if ( GetTransaction(tx.vin[i].prevout.hash,txin,hash,false) && ExtractDestination(txin.vout[tx.vin[i].prevout.n].scriptPubKey, address) ) { - fprintf(stderr, "2 notary address.%s address.%s\n", NotaryAddress.c_str(), CBitcoinAddress(address).ToString().c_str()); if ( CBitcoinAddress(address).ToString() == NotaryAddress ) numvinIsOurs++; if ( !WHITELIST_ADDRESS.empty() && CBitcoinAddress(address).ToString() == WHITELIST_ADDRESS ) numvinIsWhiteList++; } } - fprintf(stderr, "3 notary address.%s\n", NotaryAddress.c_str()); // Now we know if it was a tx sent to us, that wasnt from ourself or the whitelist address if set.. if ( numvinIsOurs != 0 ) fprintf(stderr, "We sent from address: %s vins: %d\n",NotaryAddress.c_str(),numvinIsOurs); From e101aa3f9bf3e5e831237dd5519d06a93c0a040b Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Tue, 9 Apr 2019 06:10:02 +0800 Subject: [PATCH 18/35] make -whitelistaddress= activate wallet filter --- src/wallet/wallet.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index f4a52cf24..35edc24c6 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1751,7 +1751,6 @@ extern uint8_t NOTARY_PUBKEY33[33]; extern std::string NOTARY_ADDRESS,WHITELIST_ADDRESS; extern int32_t IS_STAKED_NOTARY; extern uint64_t MIN_RECV_SATS; -bool WALLET_FILTER = true; #include "cc/CCinclude.h" bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate) @@ -1783,7 +1782,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl if (fExisted || IsMine(tx) || IsFromMe(tx) || sproutNoteData.size() > 0 || saplingNoteData.size() > 0) { // wallet filter for notary nodes. Disabled! Can be reenabled or customised for any specific use, pools could also use this to prevent wallet dwy attack. - if ( !tx.IsCoinBase() && WALLET_FILTER && !NotaryAddress.empty() ) //&& !NOTARY_ADDRESS.empty() && IS_STAKED_NOTARY > -1 ) + if ( !tx.IsCoinBase() && !WHITELIST_ADDRESS.empty() && !NotaryAddress.empty() ) //&& !NOTARY_ADDRESS.empty() && IS_STAKED_NOTARY > -1 ) { int numvinIsOurs = 0, numvinIsWhiteList = 0; // numvoutIsOurs = 0, int64_t totalvoutvalue = 0; for (size_t i = 0; i < tx.vin.size(); i++) @@ -1793,7 +1792,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl { if ( CBitcoinAddress(address).ToString() == NotaryAddress ) numvinIsOurs++; - if ( !WHITELIST_ADDRESS.empty() && CBitcoinAddress(address).ToString() == WHITELIST_ADDRESS ) + if ( CBitcoinAddress(address).ToString() == WHITELIST_ADDRESS ) numvinIsWhiteList++; } } From 2e19349105ca2813646a0240417635cba7ee9a36 Mon Sep 17 00:00:00 2001 From: jl777 Date: Mon, 8 Apr 2019 21:54:24 -1100 Subject: [PATCH 19/35] Redeem solution --- src/cc/pegs.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/cc/pegs.cpp b/src/cc/pegs.cpp index b83279276..00d76d8fd 100644 --- a/src/cc/pegs.cpp +++ b/src/cc/pegs.cpp @@ -61,7 +61,10 @@ pegs CC is able to create a coin backed (by any supported coin with gateways CC (1000 KMD, -1200 USD, 200KMD reserve, -160KMD, issue $1600 USD, 40 KMD reserve) what sort of non-liquidation withdraw would be acceptable? if the base amount 1000 KMD is reduced along with USD owed, then the reserve status will go up for the account. but that would seem to allow extra USD to be able to be issued. there should be no disadvantage from funding a withdraw, but also not any large advantage. it needs to be a neutral event.... - UNSOLVED selection, account adjustment issue + + One solution is to allow for the chance for any account to be liquidated, but the equity compensated for with a premium based on the account reserves. So in the above case, a premium of 5% on the 40KMD reserve is paid to liquidate its account. Instead of 5% premium, a lower 1% can be done if based on the MAX(correlated[daywindow],smoothed) so we get something that is close to the current marketprice. To prevent people taking advantage of the slowness of the smoothed price to adjust, there would need to be a one day delay in the withdraw. + + From a practical sense, it seems a day is a long time, so maybe having a way to pay a premium like 10%, or wait a day to get the MAX(correlated[daywindow],smoothed) price. This price "jumping" might also be taken advantage of in the deposit side, so similar to prices CC it seems good to have the MAX(correlated[daywindow],smoothed) method. Now, we have a decentralized mechanism to handle the price going lower! Combined with the fully decentralized method new USD coins are issued, makes this argubably the first decentralized blockchain that is both backed and pegged. There is the reliance on the gateways CC multisig signers, so there is a fundamental federated trust for chains without intrinsic value. From 237f11559425593a0a65554fc01d093f596b88dd Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Tue, 9 Apr 2019 18:53:32 +0800 Subject: [PATCH 20/35] Clean up some LABS related code, remove un-used/needed stuff. Adds actual working and feild tested wallet filter. Can set any amount of whitelist address's, in conf file or commandline args. fix daemon deadlock, when doing z_mergetoaddress and mining at same time (needs more testing on staking chains) Set z_mergtoaddress to use a 0 expiry height when not doing z-tx's. They were failing and peers were getting banned trying to broadcast them. --- src/komodo.h | 10 ------ src/komodo_defs.h | 4 +-- src/komodo_globals.h | 10 +++--- src/komodo_utils.h | 2 -- src/main.cpp | 3 -- src/miner.cpp | 35 +++++---------------- src/notaries_staked.cpp | 16 ++-------- src/notaries_staked.h | 1 - src/wallet/rpcwallet.cpp | 4 ++- src/wallet/wallet.cpp | 67 ++++++++++++---------------------------- 10 files changed, 40 insertions(+), 112 deletions(-) diff --git a/src/komodo.h b/src/komodo.h index 791adba33..3ceb29cc3 100644 --- a/src/komodo.h +++ b/src/komodo.h @@ -836,16 +836,6 @@ int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) int8_t numSN = numStakedNotaries(tmp_pubkeys,staked_era); UpdateNotaryAddrs(tmp_pubkeys,numSN); STAKED_ERA = staked_era; - if ( NOTARYADDRS[0][0] != 0 && NOTARY_PUBKEY33[0] != 0 ) - { - if ( (IS_STAKED_NOTARY= updateStakedNotary()) > -1 ) - { - IS_KOMODO_NOTARY = 0; - if ( MIN_RECV_SATS == -1 ) - MIN_RECV_SATS = 100000000; - fprintf(stderr, "Staked Notary Protection Active! NotaryID.%d RADD.%s ERA.%d MIN_TX_VALUE.%lu \n",IS_STAKED_NOTARY,NOTARY_ADDRESS.c_str(),staked_era,MIN_RECV_SATS); - } - } lastStakedEra = staked_era; } } diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 49aa67081..9377ea276 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -80,9 +80,9 @@ extern int32_t VERUS_MIN_STAKEAGE; extern std::string DONATION_PUBKEY; extern uint8_t ASSETCHAINS_PRIVATE; extern int32_t USE_EXTERNAL_PUBKEY; +extern char NOTARYADDRS[64][64]; int tx_height( const uint256 &hash ); -extern char NOTARYADDRS[64][36]; -extern uint8_t NUM_NOTARIES; +extern std::vector vWhiteListAddress; void komodo_netevent(std::vector payload); int32_t komodo_priceind(char *symbol); diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 1c47e72e6..eccbb34f1 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -47,12 +47,14 @@ unsigned int WITNESS_CACHE_SIZE = _COINBASE_MATURITY+10; int32_t KOMODO_MININGTHREADS = -1,IS_KOMODO_NOTARY,IS_STAKED_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAINS_SEED,KOMODO_ON_DEMAND,KOMODO_EXTERNAL_NOTARIES,KOMODO_PASSPORT_INITDONE,KOMODO_PAX,KOMODO_EXCHANGEWALLET,KOMODO_REWIND,STAKED_ERA,KOMODO_CONNECTING = -1,KOMODO_DEALERNODE,KOMODO_EXTRASATOSHI,ASSETCHAINS_FOUNDERS; int32_t KOMODO_INSYNC,KOMODO_LASTMINED,prevKOMODO_LASTMINED,KOMODO_CCACTIVATE,JUMBLR_PAUSE = 1; -std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY,ASSETCHAINS_SCRIPTPUB,NOTARY_ADDRESS,WHITELIST_ADDRESS,ASSETCHAINS_SELFIMPORT,ASSETCHAINS_CCLIB; -uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEYHASH[20],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE,ASSETCHAINS_TXPOW,NUM_NOTARIES,ASSETCHAINS_MARMARA; +std::string NOTARY_PUBKEY,ASSETCHAINS_NOTARIES,ASSETCHAINS_OVERRIDE_PUBKEY,DONATION_PUBKEY,ASSETCHAINS_SCRIPTPUB,NOTARY_ADDRESS,ASSETCHAINS_SELFIMPORT,ASSETCHAINS_CCLIB; +uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEYHASH[20],ASSETCHAINS_PUBLIC,ASSETCHAINS_PRIVATE,ASSETCHAINS_TXPOW,ASSETCHAINS_MARMARA; bool VERUS_MINTBLOCKS; std::vector Mineropret; +std::vector vWhiteListAddress; +char NOTARYADDRS[64][64]; -char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],ASSETCHAINS_USERPASS[4096],NOTARYADDRS[64][36]; +char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN],ASSETCHAINS_USERPASS[4096]; uint16_t ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,ASSETCHAINS_BEAMPORT,ASSETCHAINS_CODAPORT; uint32_t ASSETCHAIN_INIT,ASSETCHAINS_CC,KOMODO_STOPAT,KOMODO_DPOWCONFS = 1,STAKING_MIN_DIFF; uint32_t ASSETCHAINS_MAGIC = 2387029918; @@ -99,7 +101,7 @@ int32_t ASSETCHAINS_OVERWINTER = -1; uint64_t KOMODO_INTERESTSUM,KOMODO_WALLETBALANCE; int32_t ASSETCHAINS_STAKED; -uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY = 10,MIN_RECV_SATS,ASSETCHAINS_FOUNDERS_REWARD; +uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY = 10,ASSETCHAINS_FOUNDERS_REWARD; uint32_t KOMODO_INITDONE; char KMDUSERPASS[8192+512+1],BTCUSERPASS[8192]; uint16_t KMD_PORT = 7771,BITCOIND_RPCPORT = 7771; diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 2d0fe4f4e..043d7282e 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -1677,8 +1677,6 @@ void komodo_args(char *argv0) fprintf(stderr, "Cannot be STAKED and KMD notary at the same time!\n"); exit(0); } - MIN_RECV_SATS = GetArg("-mintxvalue",-1); - WHITELIST_ADDRESS = GetArg("-whitelistaddress",""); memset(ccenables,0,sizeof(ccenables)); memset(disablebits,0,sizeof(disablebits)); if ( GetBoolArg("-gen", false) != 0 ) diff --git a/src/main.cpp b/src/main.cpp index 8fbc0f1dd..faa9e6a9c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1270,9 +1270,6 @@ bool CheckTransaction(uint32_t tiptime,const CTransaction& tx, CValidationState } } -extern char NOTARYADDRS[64][36]; -extern uint8_t NUM_NOTARIES; - int32_t komodo_isnotaryvout(char *coinaddr) // from ac_private chains only { static int32_t didinit; static char notaryaddrs[sizeof(Notaries_elected1)/sizeof(*Notaries_elected1) + 1][64]; diff --git a/src/miner.cpp b/src/miner.cpp index f131bc90e..54b18195a 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -224,8 +224,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 CBlockIndex* pindexPrev = 0; { - ENTER_CRITICAL_SECTION(cs_main); - ENTER_CRITICAL_SECTION(mempool.cs); + LOCK2(cs_main,mempool.cs); pindexPrev = chainActive.LastTip(); const int nHeight = pindexPrev->GetHeight() + 1; const Consensus::Params &consensusParams = chainparams.GetConsensus(); @@ -564,11 +563,10 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 //LogPrintf("CreateNewBlock(): total size %u blocktime.%u nBits.%08x stake.%i\n", nBlockSize,blocktime,pblock->nBits,isStake); if ( ASSETCHAINS_SYMBOL[0] != 0 && isStake ) { - LEAVE_CRITICAL_SECTION(cs_main); - LEAVE_CRITICAL_SECTION(mempool.cs); uint64_t txfees,utxovalue; uint32_t txtime; uint256 utxotxid; int32_t i,siglen,numsigs,utxovout; uint8_t utxosig[512],*ptr; CMutableTransaction txStaked = CreateNewContextualCMutableTransaction(Params().GetConsensus(), stakeHeight); - + LEAVE_CRITICAL_SECTION(cs_main); + LEAVE_CRITICAL_SECTION(mempool.cs); if (ASSETCHAINS_LWMAPOS != 0) { uint32_t nBitsPOS; @@ -593,7 +591,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 { sleep(1); if ( (rand() % 100) < 1 ) - fprintf(stderr, "%u seconds until elegible, waiting.\n", blocktime-((uint32_t)GetAdjustedTime()+57)); + fprintf(stderr, "%u seconds until elegible, waiting...\n", blocktime-((uint32_t)GetAdjustedTime()+57)); if ( chainActive.LastTip()->GetHeight() >= stakeHeight ) { fprintf(stderr, "Block Arrived, reset staking loop.\n"); @@ -603,7 +601,8 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 return(0); } } - + ENTER_CRITICAL_SECTION(cs_main); + ENTER_CRITICAL_SECTION(mempool.cs); if ( siglen > 0 ) { CAmount txfees; @@ -616,7 +615,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 nFees += txfees; pblock->nTime = blocktime; //printf("staking PoS ht.%d t%u lag.%u\n",(int32_t)chainActive.LastTip()->GetHeight()+1,blocktime,(uint32_t)(GetAdjustedTime() - (blocktime-13))); - } else return(0); //fprintf(stderr,"no utxos eligible for staking\n"); + } else return(0); //fprintf(stderr,"no utxos eligible for staking\n"); } // Create coinbase tx @@ -688,11 +687,6 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 if (scriptPubKeyIn.IsPayToScriptHash() || scriptPubKeyIn.IsPayToCryptoCondition()) { fprintf(stderr,"CreateNewBlock: attempt to add timelock to pay2sh or pay2cc\n"); - if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) ) - { - LEAVE_CRITICAL_SECTION(cs_main); - LEAVE_CRITICAL_SECTION(mempool.cs); - } return 0; } @@ -714,11 +708,6 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 if ( totalsats == 0 ) { fprintf(stderr, "Could not create notary payment, trying again.\n"); - if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) ) - { - LEAVE_CRITICAL_SECTION(cs_main); - LEAVE_CRITICAL_SECTION(mempool.cs); - } return(0); } fprintf(stderr, "Created notary payment coinbase totalsat.%lu\n",totalsats); @@ -789,11 +778,6 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 else { fprintf(stderr,"error adding notaryvin, need to create 0.0001 utxos\n"); - if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) ) - { - LEAVE_CRITICAL_SECTION(cs_main); - LEAVE_CRITICAL_SECTION(mempool.cs); - } return(0); } } @@ -808,11 +792,6 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 //fprintf(stderr,"valid\n"); } } - if ( ASSETCHAINS_SYMBOL[0] == 0 || (ASSETCHAINS_SYMBOL[0] != 0 && !isStake) ) - { - LEAVE_CRITICAL_SECTION(cs_main); - LEAVE_CRITICAL_SECTION(mempool.cs); - } //fprintf(stderr,"done new block\n"); return pblocktemplate.release(); } diff --git a/src/notaries_staked.cpp b/src/notaries_staked.cpp index a3278ac12..0b7c97ceb 100644 --- a/src/notaries_staked.cpp +++ b/src/notaries_staked.cpp @@ -4,11 +4,11 @@ #include "cc/CCinclude.h" #include -extern char NOTARYADDRS[64][36]; +extern char NOTARYADDRS[64][64]; extern std::string NOTARY_ADDRESS,NOTARY_PUBKEY; extern int32_t STAKED_ERA,IS_STAKED_NOTARY,IS_KOMODO_NOTARY; extern pthread_mutex_t staked_mutex; -extern uint8_t NOTARY_PUBKEY33[33],NUM_NOTARIES; +extern uint8_t NOTARY_PUBKEY33[33]; int8_t is_STAKED(const char *chain_name) { @@ -46,16 +46,6 @@ int32_t STAKED_era(int timestamp) return(0); }; -int8_t updateStakedNotary() { - std::string notaryname; - char Raddress[18]; uint8_t pubkey33[33]; - decode_hex(pubkey33,33,(char *)NOTARY_PUBKEY.c_str()); - pubkey2addr((char *)Raddress,(uint8_t *)pubkey33); - NOTARY_ADDRESS.clear(); - NOTARY_ADDRESS.assign(Raddress); - return(StakedNotaryID(notaryname,Raddress)); -} - int8_t StakedNotaryID(std::string ¬aryname, char *Raddress) { if ( STAKED_ERA != 0 ) { @@ -116,7 +106,6 @@ void UpdateNotaryAddrs(uint8_t pubkeys[64][33],int8_t numNotaries) { // null pubkeys, era 0. pthread_mutex_lock(&staked_mutex); memset(NOTARYADDRS,0,sizeof(NOTARYADDRS)); - NUM_NOTARIES = 0; pthread_mutex_unlock(&staked_mutex); } else @@ -125,7 +114,6 @@ void UpdateNotaryAddrs(uint8_t pubkeys[64][33],int8_t numNotaries) { pthread_mutex_lock(&staked_mutex); for (int i = 0; i builder; if (isToSaplingZaddr || saplingNoteInputs.size() > 0) { builder = TransactionBuilder(Params().GetConsensus(), nextBlockHeight, pwalletMain); - } + } else + contextualTx.nExpiryHeight = 0; // set non z-tx to have no expiry height. + // Create operation and add to global queue std::shared_ptr q = getAsyncRPCQueue(); std::shared_ptr operation( diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 35edc24c6..9b2975db1 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -38,6 +38,7 @@ #include "crypter.h" #include "coins.h" #include "zcash/zip32.h" +#include "cc/CCinclude.h" #include @@ -1747,11 +1748,6 @@ bool CWallet::UpdatedNoteData(const CWalletTx& wtxIn, CWalletTx& wtx) * pblock is optional, but should be provided if the transaction is known to be in a block. * If fUpdate is true, existing transactions will be updated. */ -extern uint8_t NOTARY_PUBKEY33[33]; -extern std::string NOTARY_ADDRESS,WHITELIST_ADDRESS; -extern int32_t IS_STAKED_NOTARY; -extern uint64_t MIN_RECV_SATS; -#include "cc/CCinclude.h" bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate) { @@ -1777,14 +1773,20 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl char Raddress[64]; pubkey2addr((char *)Raddress,(uint8_t *)NOTARY_PUBKEY33); NotaryAddress.assign(Raddress); - fprintf(stderr, "notary address set to %s\n", NotaryAddress.c_str()); + vWhiteListAddress = mapMultiArgs["-whitelistaddress"]; + if ( !vWhiteListAddress.empty() ) + { + fprintf(stderr, "Activated Wallet Filter \n Notary Address: %s \n Adding whitelist address's:\n", NotaryAddress.c_str()); + for ( auto wladdr : vWhiteListAddress ) + fprintf(stderr, " %s\n", wladdr.c_str()); + } } if (fExisted || IsMine(tx) || IsFromMe(tx) || sproutNoteData.size() > 0 || saplingNoteData.size() > 0) { - // wallet filter for notary nodes. Disabled! Can be reenabled or customised for any specific use, pools could also use this to prevent wallet dwy attack. - if ( !tx.IsCoinBase() && !WHITELIST_ADDRESS.empty() && !NotaryAddress.empty() ) //&& !NOTARY_ADDRESS.empty() && IS_STAKED_NOTARY > -1 ) + // wallet filter for notary nodes. Enables by setting -whitelistaddress= as startup param or in conf file (works same as -addnode byut with R-address's) + if ( !tx.IsCoinBase() && !vWhiteListAddress.empty() && !NotaryAddress.empty() ) { - int numvinIsOurs = 0, numvinIsWhiteList = 0; // numvoutIsOurs = 0, int64_t totalvoutvalue = 0; + int numvinIsOurs = 0, numvinIsWhiteList = 0; for (size_t i = 0; i < tx.vin.size(); i++) { uint256 hash; CTransaction txin; CTxDestination address; @@ -1792,50 +1794,21 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl { if ( CBitcoinAddress(address).ToString() == NotaryAddress ) numvinIsOurs++; - if ( CBitcoinAddress(address).ToString() == WHITELIST_ADDRESS ) - numvinIsWhiteList++; - } - } - // Now we know if it was a tx sent to us, that wasnt from ourself or the whitelist address if set.. - if ( numvinIsOurs != 0 ) - fprintf(stderr, "We sent from address: %s vins: %d\n",NotaryAddress.c_str(),numvinIsOurs); - if ( numvinIsWhiteList != 0 ) - fprintf(stderr, "We received from whitelisted address: %s\n",WHITELIST_ADDRESS.c_str()); - // Count vouts, check if OUR notary address is the receiver. - if ( numvinIsOurs == 0 && numvinIsWhiteList == 0 ) - { - return false; - /*/ if MIN_RECV_SATS is 0, we are on full lock down mode, accept NO transactions. - if ( 1 ) { //MIN_RECV_SATS == 0 ) { - fprintf(stderr, "This node is on full lock down all txs are ignored! \n"); - return false; - } - for (size_t i = 0; i < tx.vout.size() ; i++) - { - CTxDestination address2; - if ( ExtractDestination(tx.vout[i].scriptPubKey, address2)) + for ( auto wladdr : vWhiteListAddress ) { - if ( CBitcoinAddress(address2).ToString() == NOTARY_ADDRESS ) + if ( CBitcoinAddress(address).ToString() == wladdr ) { - numvoutIsOurs++; - totalvoutvalue += tx.vout[i].nValue; + //fprintf(stderr, "We received from whitelisted address.%s\n", wladdr.c_str()); + numvinIsWhiteList++; } } } - // If no vouts are to the notary address we will ignore them. - if ( numvoutIsOurs == 0 ) { - fprintf(stderr, "Received transaction to address other than notary address, ignored! \n"); - return false; - } - fprintf(stderr, "address: %s received %ld sats from %d vouts.\n",NOTARY_ADDRESS.c_str(),totalvoutvalue,(int32_t)numvoutIsOurs); - // here we add calculation for number if vouts received, average size and determine if we accept them to wallet or not. - int64_t avgVoutSize = totalvoutvalue / numvoutIsOurs; - if ( avgVoutSize < MIN_RECV_SATS ) { - // average vout size is less than set minimum, default is 1 coin, we will ignore it - fprintf(stderr, "ignored: %d vouts average size of %ld sats.\n",numvoutIsOurs, (long)avgVoutSize); - return false; - } */ } + // Now we know if it was a tx sent to us, by either a whitelisted address, or ourself. + if ( numvinIsOurs != 0 ) + fprintf(stderr, "We sent from address: %s vins: %d\n",NotaryAddress.c_str(),numvinIsOurs); + if ( numvinIsOurs == 0 && numvinIsWhiteList == 0 ) + return false; } CWalletTx wtx(this,tx); From bce0b87e6f2735dff3c1137780cb6418da3798b8 Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Wed, 10 Apr 2019 02:11:40 +0800 Subject: [PATCH 21/35] . --- src/komodo_bitcoind.h | 32 ++++++++++++---------- src/rpc/client.cpp | 1 + src/rpc/crosschain.cpp | 60 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 78 insertions(+), 15 deletions(-) diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index e537df018..aa21896aa 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -1917,33 +1917,37 @@ uint64_t komodo_notarypay(CMutableTransaction &txNew, std::vector &Notar return(total); } -uint64_t komodo_checknotarypay(CBlock *pblock,int32_t height) +bool GetNotarisationNotaries(uint8_t notarypubkeys[64][33], int8_t &numNN, const std::vector &vin, std::vector &NotarisationNotaries) { - std::vector NotarisationNotaries; - uint32_t timestamp = pblock->nTime; - int8_t numSN = 0; uint8_t notarypubkeys[64][33] = {0}; - numSN = komodo_notaries(notarypubkeys, height, timestamp); - - // No point going further, no notaries can be paid. - if ( notarypubkeys[0][0] == 0 ) - return(0); - uint8_t *script; int32_t scriptlen; - // Loop over the notarisation and extract the position of the participating notaries in the array of pukeys for this era. - BOOST_FOREACH(const CTxIn& txin, pblock->vtx[1].vin) + if ( notarypubkeys[0][0] == 0 ) + return false; + BOOST_FOREACH(const CTxIn& txin, vin) { uint256 hash; CTransaction tx1; if ( GetTransaction(txin.prevout.hash,tx1,hash,false) ) { - for (int8_t i = 0; i < numSN; i++) + for (int8_t i = 0; i < numNN; i++) { script = (uint8_t *)&tx1.vout[txin.prevout.n].scriptPubKey[0]; scriptlen = (int32_t)tx1.vout[txin.prevout.n].scriptPubKey.size(); if ( scriptlen == 35 && script[0] == 33 && script[34] == OP_CHECKSIG && memcmp(script+1,notarypubkeys[i],33) == 0 ) NotarisationNotaries.push_back(i); } - } + } else return false; } + return true; +} + +uint64_t komodo_checknotarypay(CBlock *pblock,int32_t height) +{ + std::vector NotarisationNotaries; uint8_t *script; int32_t scriptlen; + uint64_t timestamp = pblock->nTime; + int8_t numSN = 0; uint8_t notarypubkeys[64][33] = {0}; + numSN = komodo_notaries(notarypubkeys, height, timestamp); + if ( !GetNotarisationNotaries(notarypubkeys, numSN, pblock->vtx[1].vin, NotarisationNotaries) ) + return(0); + // check a notary didnt sign twice (this would be an invalid notarisation later on and cause problems) std::set checkdupes( NotarisationNotaries.begin(), NotarisationNotaries.end() ); if ( checkdupes.size() != NotarisationNotaries.size() ) { diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 19910b25c..cab89092c 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -171,6 +171,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "assetchainproof", 1}, { "crosschainproof", 1}, { "getproofroot", 2}, + { "getNotarisationsForBlock", 0}, { "height_MoM", 1}, { "calc_MoM", 2}, }; diff --git a/src/rpc/crosschain.cpp b/src/rpc/crosschain.cpp index 710f99f09..72c24086f 100644 --- a/src/rpc/crosschain.cpp +++ b/src/rpc/crosschain.cpp @@ -33,6 +33,7 @@ #include "script/script_error.h" #include "script/sign.h" #include "script/standard.h" +#include "notaries_staked.h" #include "key_io.h" @@ -49,6 +50,7 @@ int32_t komodo_MoM(int32_t *notarized_htp,uint256 *MoMp,uint256 *kmdtxidp,int32_ int32_t komodo_MoMoMdata(char *hexstr,int32_t hexsize,struct komodo_ccdataMoMoM *mdata,char *symbol,int32_t kmdheight,int32_t notarized_height); struct komodo_ccdata_entry *komodo_allMoMs(int32_t *nump,uint256 *MoMoMp,int32_t kmdstarti,int32_t kmdendi); uint256 komodo_calcMoM(int32_t height,int32_t MoMdepth); +int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp); extern std::string ASSETCHAINS_SELFIMPORT; uint256 Parseuint256(char *hexstr); @@ -406,7 +408,63 @@ UniValue selfimport(const UniValue& params, bool fHelp) return result; } +bool GetNotarisationNotaries(uint8_t notarypubkeys[64][33], int8_t &numNN, const std::vector &vin, std::vector &NotarisationNotaries); + UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp) +{ + // TODO take timestamp as param, and loop blockindex to get starting/finish height. + if (fHelp || params.size() != 1) + throw runtime_error("getNotarisationsForBlock height\n\n" + "Takes a block height and returns notarisation information " + "within the block"); + + LOCK(cs_main); + int32_t height = params[0].get_int(); + if ( height < 0 || height > chainActive.Height() ) + throw runtime_error("height out of range.\n"); + + uint256 blockHash = chainActive[height]->GetBlockHash(); + + NotarisationsInBlock nibs; + GetBlockNotarisations(blockHash, nibs); + UniValue out(UniValue::VOBJ); + //out.push_back(make_pair("blocktime",(int))); + UniValue labs(UniValue::VARR); + UniValue kmd(UniValue::VARR); + // Gets KMD notaries on KMD... but LABS notaries on labs chains needs to be fixed so LABS are identified on KMD. + int8_t numNN = 0; uint8_t notarypubkeys[64][33] = {0}; + numNN = komodo_notaries(notarypubkeys, height, chainActive[height]->nTime); + + BOOST_FOREACH(const Notarisation& n, nibs) + { + UniValue item(UniValue::VOBJ); UniValue notaryarr(UniValue::VARR); std::vector NotarisationNotaries; + if ( is_STAKED(n.second.symbol) != 0 ) + continue; // for now just skip this... need to fetch diff pubkeys for these chains. labs.push_back(item); + uint256 hash; CTransaction tx; + if ( GetTransaction(n.first,tx,hash,false) ) + { + if ( !GetNotarisationNotaries(notarypubkeys, numNN, tx.vin, NotarisationNotaries) ) + continue; + if ( NotarisationNotaries.size() < numNN/5 ) + continue; + } + item.push_back(make_pair("txid", n.first.GetHex())); + item.push_back(make_pair("chain", n.second.symbol)); + item.push_back(make_pair("height", (int)n.second.height)); + item.push_back(make_pair("blockhash", n.second.blockHash.GetHex())); + item.push_back(make_pair("KMD_height", height)); // for when timstamp input is used. + + for ( auto notary : NotarisationNotaries ) + notaryarr.push_back(notary); + item.push_back(make_pair("notaries",notaryarr)); + kmd.push_back(item); + } + out.push_back(make_pair("KMD", kmd)); + //out.push_back(make_pair("LABS", labs)); + return out; +} + +/*UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) throw runtime_error("getNotarisationsForBlock blockHash\n\n" @@ -426,7 +484,7 @@ UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp) out.push_back(item); } return out; -} +}*/ UniValue scanNotarisationsDB(const UniValue& params, bool fHelp) From df79068ab65e64eb8d91cdfafcc5528560f40a12 Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Wed, 10 Apr 2019 02:12:52 +0800 Subject: [PATCH 22/35] y --- src/notarystats.py | 99 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 src/notarystats.py diff --git a/src/notarystats.py b/src/notarystats.py new file mode 100644 index 000000000..cc67ad10e --- /dev/null +++ b/src/notarystats.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 +""" +build komodod from here: https://github.com/blackjok3rtt/komodo/tree/nota_stats +sudo apt-get install python3-dev +sudo apt-get install python3 libgnutls28-dev libssl-dev +sudo apt-get install python3-pip +pip3 install setuptools +pip3 install wheel +pip3 install base58 slick-bitcoinrpc +./notarystats.py +------------------------------------------------ +""" +import platform +import os +import re +import sys +import time +import pprint +from slickrpc import Proxy + +# fucntion to define rpc_connection +def def_credentials(chain): + rpcport = ''; + operating_system = platform.system() + if operating_system == 'Darwin': + ac_dir = os.environ['HOME'] + '/Library/Application Support/Komodo' + elif operating_system == 'Linux': + ac_dir = os.environ['HOME'] + '/.komodo' + elif operating_system == 'Windows': + ac_dir = '%s/komodo/' % os.environ['APPDATA'] + if chain == 'KMD': + coin_config_file = str(ac_dir + '/komodo.conf') + else: + coin_config_file = str(ac_dir + '/' + chain + '/' + chain + '.conf') + with open(coin_config_file, 'r') as f: + for line in f: + l = line.rstrip() + if re.search('rpcuser', l): + rpcuser = l.replace('rpcuser=', '') + elif re.search('rpcpassword', l): + rpcpassword = l.replace('rpcpassword=', '') + elif re.search('rpcport', l): + rpcport = l.replace('rpcport=', '') + if len(rpcport) == 0: + if chain == 'KMD': + rpcport = 7771 + else: + print("rpcport not in conf file, exiting") + print("check " + coin_config_file) + exit(1) + return (Proxy("http://%s:%s@127.0.0.1:%d" % (rpcuser, rpcpassword, int(rpcport)))) + + +rpc = def_credentials('KMD') +pp = pprint.PrettyPrinter(indent=2) + +#Second time filter for assetchains (block 821657) +notarynames = [ "0dev1_jl777", "0dev2_kolo", "0dev3_kolo", "0dev4_decker", "a-team_SH", "artik_AR", "artik_EU", "artik_NA", "artik_SH", "badass_EU", "badass_NA", "batman_AR", "batman_SH", "ca333_EU", "chainmakers_EU", "chainmakers_NA", "chainstrike_SH", "cipi_AR", "cipi_NA", "crackers_EU", "crackers_NA", "dwy_EU", "emmanux_SH", "etszombi_EU", "fullmoon_AR", "fullmoon_NA", "fullmoon_SH", "goldenman_EU", "indenodes_AR", "indenodes_EU", "indenodes_NA", "indenodes_SH", "jackson_AR", "jeezy_EU", "karasugoi_NA", "komodoninja_EU", "komodoninja_SH", "komodopioneers_SH", "libscott_SH", "lukechilds_AR", "madmax_AR", "meshbits_AR", "meshbits_SH", "metaphilibert_AR", "metaphilibert_SH", "patchkez_SH", "pbca26_NA", "peer2cloud_AR", "peer2cloud_SH", "polycryptoblog_NA", "hyper_AR", "hyper_EU", "hyper_SH", "hyper_NA", "popcornbag_AR", "popcornbag_NA", "alien_AR", "alien_EU", "thegaltmines_NA", "titomane_AR", "titomane_EU", "titomane_SH", "webworker01_NA", "xrobesx_NA" ] +notaries = 64 * [0] + +startheight = 821657 +stopheight = 1300000 +for i in range(startheight,stopheight): + ret = rpc.getNotarisationsForBlock(i) + KMD = ret['KMD'] + if len(KMD) > 0: + for obj in KMD: + # sanity check, KMD nota dont appear in DB anyway! + if obj['chain'] == 'KMD': + continue; + for notary in obj['notaries']: + notaries[notary] = notaries[notary] + 1 + +i = 0 +SH = [] +AR = [] +EU = [] +NA = [] +for notary in notaries: + tmpnotary = {} + tmpnotary['node'] = notarynames[i] + tmpnotary['ac_count'] = notary + if notarynames[i].endswith('SH'): + SH.append(tmpnotary) + elif notarynames[i].endswith('AR'): + AR.append(tmpnotary) + elif notarynames[i].endswith('EU'): + EU.append(tmpnotary) + elif notarynames[i].endswith('NA'): + NA.append(tmpnotary) + i = i + 1 + +regions = {} +regions['SH'] = sorted(SH, key=lambda k: k['ac_count'], reverse=True) +regions['AR'] = sorted(AR, key=lambda k: k['ac_count'], reverse=True) +regions['EU'] = sorted(EU, key=lambda k: k['ac_count'], reverse=True) +regions["NA"] = sorted(NA, key=lambda k: k['ac_count'], reverse=True) + +pp.pprint(regions) From e688959c6e3343f1c93c24b4642310ba4e93a062 Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Wed, 10 Apr 2019 11:41:29 +0800 Subject: [PATCH 23/35] ... --- src/notarystats.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) mode change 100644 => 100755 src/notarystats.py diff --git a/src/notarystats.py b/src/notarystats.py old mode 100644 new mode 100755 index cc67ad10e..c8b3ab1f1 --- a/src/notarystats.py +++ b/src/notarystats.py @@ -58,14 +58,14 @@ pp = pprint.PrettyPrinter(indent=2) notarynames = [ "0dev1_jl777", "0dev2_kolo", "0dev3_kolo", "0dev4_decker", "a-team_SH", "artik_AR", "artik_EU", "artik_NA", "artik_SH", "badass_EU", "badass_NA", "batman_AR", "batman_SH", "ca333_EU", "chainmakers_EU", "chainmakers_NA", "chainstrike_SH", "cipi_AR", "cipi_NA", "crackers_EU", "crackers_NA", "dwy_EU", "emmanux_SH", "etszombi_EU", "fullmoon_AR", "fullmoon_NA", "fullmoon_SH", "goldenman_EU", "indenodes_AR", "indenodes_EU", "indenodes_NA", "indenodes_SH", "jackson_AR", "jeezy_EU", "karasugoi_NA", "komodoninja_EU", "komodoninja_SH", "komodopioneers_SH", "libscott_SH", "lukechilds_AR", "madmax_AR", "meshbits_AR", "meshbits_SH", "metaphilibert_AR", "metaphilibert_SH", "patchkez_SH", "pbca26_NA", "peer2cloud_AR", "peer2cloud_SH", "polycryptoblog_NA", "hyper_AR", "hyper_EU", "hyper_SH", "hyper_NA", "popcornbag_AR", "popcornbag_NA", "alien_AR", "alien_EU", "thegaltmines_NA", "titomane_AR", "titomane_EU", "titomane_SH", "webworker01_NA", "xrobesx_NA" ] notaries = 64 * [0] -startheight = 821657 -stopheight = 1300000 +startheight = 1300000 #821657 +stopheight = 99999999 for i in range(startheight,stopheight): ret = rpc.getNotarisationsForBlock(i) KMD = ret['KMD'] if len(KMD) > 0: for obj in KMD: - # sanity check, KMD nota dont appear in DB anyway! + #for now skip KMD for this. As official stats are from BTC chain? if obj['chain'] == 'KMD': continue; for notary in obj['notaries']: From 3d83dda142d7fceafd951255d8738e90bc0521cb Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Wed, 10 Apr 2019 12:07:31 +0800 Subject: [PATCH 24/35] fix script --- src/notarystats.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/notarystats.py b/src/notarystats.py index c8b3ab1f1..b606db1a6 100755 --- a/src/notarystats.py +++ b/src/notarystats.py @@ -54,18 +54,18 @@ def def_credentials(chain): rpc = def_credentials('KMD') pp = pprint.PrettyPrinter(indent=2) -#Second time filter for assetchains (block 821657) notarynames = [ "0dev1_jl777", "0dev2_kolo", "0dev3_kolo", "0dev4_decker", "a-team_SH", "artik_AR", "artik_EU", "artik_NA", "artik_SH", "badass_EU", "badass_NA", "batman_AR", "batman_SH", "ca333_EU", "chainmakers_EU", "chainmakers_NA", "chainstrike_SH", "cipi_AR", "cipi_NA", "crackers_EU", "crackers_NA", "dwy_EU", "emmanux_SH", "etszombi_EU", "fullmoon_AR", "fullmoon_NA", "fullmoon_SH", "goldenman_EU", "indenodes_AR", "indenodes_EU", "indenodes_NA", "indenodes_SH", "jackson_AR", "jeezy_EU", "karasugoi_NA", "komodoninja_EU", "komodoninja_SH", "komodopioneers_SH", "libscott_SH", "lukechilds_AR", "madmax_AR", "meshbits_AR", "meshbits_SH", "metaphilibert_AR", "metaphilibert_SH", "patchkez_SH", "pbca26_NA", "peer2cloud_AR", "peer2cloud_SH", "polycryptoblog_NA", "hyper_AR", "hyper_EU", "hyper_SH", "hyper_NA", "popcornbag_AR", "popcornbag_NA", "alien_AR", "alien_EU", "thegaltmines_NA", "titomane_AR", "titomane_EU", "titomane_SH", "webworker01_NA", "xrobesx_NA" ] notaries = 64 * [0] -startheight = 1300000 #821657 -stopheight = 99999999 +startheight = 821657 #Second time filter for assetchains (block 821657) for KMD its 814000 +stopheight = rpc.getblockcount() # @kolo what height does season end?! for i in range(startheight,stopheight): ret = rpc.getNotarisationsForBlock(i) KMD = ret['KMD'] if len(KMD) > 0: for obj in KMD: - #for now skip KMD for this. As official stats are from BTC chain? + #for now skip KMD for this. As official stats are from BTC chain + # this can be reversed to !== to count KMD numbers :) if obj['chain'] == 'KMD': continue; for notary in obj['notaries']: From 2fbb858beff294255787898d38963c1222ba2346 Mon Sep 17 00:00:00 2001 From: blackjok3rtt <30971146+blackjok3rtt@users.noreply.github.com> Date: Wed, 10 Apr 2019 12:27:53 +0800 Subject: [PATCH 25/35] remove git link --- src/notarystats.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/notarystats.py b/src/notarystats.py index b606db1a6..0e7673833 100755 --- a/src/notarystats.py +++ b/src/notarystats.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 """ -build komodod from here: https://github.com/blackjok3rtt/komodo/tree/nota_stats sudo apt-get install python3-dev sudo apt-get install python3 libgnutls28-dev libssl-dev sudo apt-get install python3-pip From 2e2bb2b51883c2e2479df531e1cff33a624e3046 Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Wed, 10 Apr 2019 16:53:08 +0800 Subject: [PATCH 26/35] fix getsnapshot2 thanks to dimxy's advice. --- src/txdb.cpp | 28 +++++++++++++--------------- src/txdb.h | 2 +- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/txdb.cpp b/src/txdb.cpp index 93000d9fb..4c9ea31ca 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -458,7 +458,7 @@ uint32_t komodo_segid32(char *coinaddr); {"RD6GgnrMpPaTSMn8vai6yiGA7mN4QGPVMY", 1} \ }; -int32_t CBlockTreeDB::Snapshot2(int64_t dustthreshold, int32_t top, bool fRPC ,std::vector > &vaddr, UniValue &ret) +int32_t CBlockTreeDB::Snapshot2(int64_t dustthreshold, int32_t top ,std::vector > &vaddr, UniValue *ret) { int64_t total = 0; int64_t totalAddresses = 0; std::string address; int64_t utxos = 0; int64_t ignoredAddresses = 0, cryptoConditionsUTXOs = 0, cryptoConditionsTotals = 0; @@ -542,30 +542,28 @@ int32_t CBlockTreeDB::Snapshot2(int64_t dustthreshold, int32_t top, bool fRPC ,s if ( top == topN ) break; } - // this is for the snapshot RPC, you can skip this by passing false to the 3rd arugment. - // Still needs UniValue defined to use SnapShot2 though, can this be changed to just pass 0? - // I tried to make it a pointer, and check if the pointer was 0, but UniValue class didnt like that. - if ( fRPC ) + // this is for the snapshot RPC, you can skip this by passing a 0 as the last argument. + if (ret) { // Total amount in this snapshot, which is less than circulating supply if top parameter is used // Use the address_total for a total of all address included when using top parameter. - ret.push_back(make_pair("total", (double) (total+cryptoConditionsTotals)/ COIN )); + ret->push_back(make_pair("total", (double) (total+cryptoConditionsTotals)/ COIN )); // Average amount in each address of this snapshot - ret.push_back(make_pair("average",(double) (total/COIN) / totalAddresses )); + ret->push_back(make_pair("average",(double) (total/COIN) / totalAddresses )); // Total number of utxos processed in this snaphot - ret.push_back(make_pair("utxos", utxos)); + ret->push_back(make_pair("utxos", utxos)); // Total number of addresses in this snaphot - ret.push_back(make_pair("total_addresses", top ? top : totalAddresses )); + ret->push_back(make_pair("total_addresses", top ? top : totalAddresses )); // Total number of ignored addresses in this snaphot - ret.push_back(make_pair("ignored_addresses", ignoredAddresses)); + ret->push_back(make_pair("ignored_addresses", ignoredAddresses)); // Total number of crypto condition utxos we skipped - ret.push_back(make_pair("skipped_cc_utxos", cryptoConditionsUTXOs)); + ret->push_back(make_pair("skipped_cc_utxos", cryptoConditionsUTXOs)); // Total value of skipped crypto condition utxos - ret.push_back(make_pair("cc_utxo_value", (double) cryptoConditionsTotals / COIN)); + ret->push_back(make_pair("cc_utxo_value", (double) cryptoConditionsTotals / COIN)); // total of all the address's, does not count coins in CC vouts. - ret.push_back(make_pair("address_total", (double) total/ COIN )); + ret->push_back(make_pair("address_total", (double) total/ COIN )); // The snapshot finished at this block height - ret.push_back(make_pair("ending_height", chainActive.Height())); + ret->push_back(make_pair("ending_height", chainActive.Height())); } return(topN); } @@ -577,7 +575,7 @@ UniValue CBlockTreeDB::Snapshot(int top) UniValue result(UniValue::VOBJ); UniValue addressesSorted(UniValue::VARR); result.push_back(Pair("start_time", (int) time(NULL))); - if ( Snapshot2(0,top,true,vaddr,result) != 0 ) + if ( Snapshot2(0,top,vaddr,&result) != 0 ) { for (std::vector>::iterator it = vaddr.begin(); it!=vaddr.end(); ++it) { diff --git a/src/txdb.h b/src/txdb.h index 8b98994a2..b4c4cd6bd 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -116,7 +116,7 @@ public: bool LoadBlockIndexGuts(); bool blockOnchainActive(const uint256 &hash); UniValue Snapshot(int top); - int32_t Snapshot2(int64_t dustthreshold, int32_t top, bool fRPC ,std::vector > &vaddr, UniValue &ret); + int32_t Snapshot2(int64_t dustthreshold, int32_t top,std::vector > &vaddr, UniValue *ret); }; #endif // BITCOIN_TXDB_H From ba0fda90b278fd51cf1b2b444ea6bea6916dc9a8 Mon Sep 17 00:00:00 2001 From: jl777 Date: Wed, 10 Apr 2019 02:09:18 -1100 Subject: [PATCH 27/35] Small changes --- src/komodo_gateway.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index ba15746e0..5aabbffd5 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1551,7 +1551,7 @@ void komodo_passport_iteration() extern std::vector Mineropret; // opreturn data set by the data gathering code #define PRICES_MAXCHANGE (COIN / 100) // maximum acceptable change, set at 1% #define PRICES_SIZEBIT0 (sizeof(uint32_t) * 4) // 4 uint32_t unixtimestamp, BTCUSD, BTCGBP and BTCEUR -#define KOMODO_LOCALPRICE_CACHESIZE 7 +#define KOMODO_LOCALPRICE_CACHESIZE 13 #define KOMODO_MAXPRICES 2048 #define issue_curl(cmdstr) bitcoind_RPC(0,(char *)"CBCOINBASE",cmdstr,0,0,0) @@ -1815,7 +1815,10 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i break; } if ( j == KOMODO_LOCALPRICE_CACHESIZE ) + { + komodo_queuelocalprice(1,block.GetHash(),i,prevbits[i]); break; + } } else if ( maxflag < 0 && localbits[i] > prevbits[i] ) { @@ -1828,7 +1831,10 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i break; } if ( j == KOMODO_LOCALPRICE_CACHESIZE ) + { + komodo_queuelocalprice(-1,block.GetHash(),i,prevbits[i]); break; + } } } } From ae7c5ee027aa4db23e7b919f77d413bc9506655e Mon Sep 17 00:00:00 2001 From: jl777 Date: Wed, 10 Apr 2019 02:13:07 -1100 Subject: [PATCH 28/35] Fix declaration --- src/komodo_gateway.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 5aabbffd5..44ec7c9f3 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1720,11 +1720,10 @@ CScript komodo_mineropret(int32_t nHeight) The only way komodo_opretvalidate() doesnt return an error is if maxflag is set or it is within tolerance of both the prior block and the local data. The local data validation only happens if it is a recent block and not a block from the past as the local node is only getting the current price data. */ -// for PRICES: reconsiderblock 002aca768b09dfcf36bd934ab34b23983148b116e12cb0b6e1a3f895d1db63aa -// and -// reconsiderblock 0034cf582018eacc0b4ae001491ce460113514cb1a3f217567ef4a2207de361a -// reconsiderbloc 000abf51c023b64af327c50c1b060797b8cb281c696d30ab92fd002a8b8c9aea -// are needed to sync past initial blocks with different data set +void komodo_queuelocalprice(int32_t dir,uint256 blockhash,int32_t ind,uint32_t pricebits) +{ + +} int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,int32_t nHeight,CScript scriptPubKey) { @@ -1816,7 +1815,7 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i } if ( j == KOMODO_LOCALPRICE_CACHESIZE ) { - komodo_queuelocalprice(1,block.GetHash(),i,prevbits[i]); + komodo_queuelocalprice(1,block.GetBlockHash(),i,prevbits[i]); break; } } @@ -1832,7 +1831,7 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i } if ( j == KOMODO_LOCALPRICE_CACHESIZE ) { - komodo_queuelocalprice(-1,block.GetHash(),i,prevbits[i]); + komodo_queuelocalprice(-1,block.GetBlockHash(),i,prevbits[i]); break; } } From 6618a43e8a8e137243572ccfd8d2b10dec1d49c2 Mon Sep 17 00:00:00 2001 From: jl777 Date: Wed, 10 Apr 2019 02:14:07 -1100 Subject: [PATCH 29/35] -> --- src/komodo_gateway.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 44ec7c9f3..82491941f 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1815,7 +1815,7 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i } if ( j == KOMODO_LOCALPRICE_CACHESIZE ) { - komodo_queuelocalprice(1,block.GetBlockHash(),i,prevbits[i]); + komodo_queuelocalprice(1,block->GetBlockHash(),i,prevbits[i]); break; } } @@ -1831,7 +1831,7 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i } if ( j == KOMODO_LOCALPRICE_CACHESIZE ) { - komodo_queuelocalprice(-1,block.GetBlockHash(),i,prevbits[i]); + komodo_queuelocalprice(-1,block->GetBlockHash(),i,prevbits[i]); break; } } From 137f51651603c5a681699c6d3c9cd7202a55f9c1 Mon Sep 17 00:00:00 2001 From: jl777 Date: Wed, 10 Apr 2019 02:16:07 -1100 Subject: [PATCH 30/35] GetHash() --- src/komodo_gateway.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 82491941f..3db8bfb1a 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1815,7 +1815,7 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i } if ( j == KOMODO_LOCALPRICE_CACHESIZE ) { - komodo_queuelocalprice(1,block->GetBlockHash(),i,prevbits[i]); + komodo_queuelocalprice(1,block->GetHash(),i,prevbits[i]); break; } } @@ -1831,7 +1831,7 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i } if ( j == KOMODO_LOCALPRICE_CACHESIZE ) { - komodo_queuelocalprice(-1,block->GetBlockHash(),i,prevbits[i]); + komodo_queuelocalprice(-1,block->GetHash(),i,prevbits[i]); break; } } From a2cdadf17de5e7c0b06e69f21ee3612075d52ff5 Mon Sep 17 00:00:00 2001 From: jl777 Date: Wed, 10 Apr 2019 02:43:11 -1100 Subject: [PATCH 31/35] Add auto resync for local prices --- src/komodo_gateway.h | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 3db8bfb1a..70a69ebc8 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1720,17 +1720,33 @@ CScript komodo_mineropret(int32_t nHeight) The only way komodo_opretvalidate() doesnt return an error is if maxflag is set or it is within tolerance of both the prior block and the local data. The local data validation only happens if it is a recent block and not a block from the past as the local node is only getting the current price data. */ -void komodo_queuelocalprice(int32_t dir,uint256 blockhash,int32_t ind,uint32_t pricebits) + +struct komodo_extremeprice { - + uint256 blockhash; + uint32_t pricebits,timestamp; + int32_t height; + int16_t dir,ind; +} ExtremePrice; + +void komodo_queuelocalprice(int32_t dir,int32_t height,uint32_t timestamp,uint256 blockhash,int32_t ind,uint32_t pricebits) +{ + ExtremePrice.dir = dir; + ExtremePrice.height = height; + ExtremePrice.blockhash = blockhash; + ExtremePrice.ind = ind; + ExtremePrice.timestamp = timestamp; + ExtremePrice.pricebits = pricebits; } int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,int32_t nHeight,CScript scriptPubKey) { int32_t testchain_exemption = 0; - std::vector vopret; char maxflags[KOMODO_MAXPRICES]; double btcusd,btcgbp,btceur; uint32_t localbits[KOMODO_MAXPRICES],pricebits[KOMODO_MAXPRICES],prevbits[KOMODO_MAXPRICES],newprice; int32_t i,j,prevtime,maxflag,lag,lag2,lag3,n,errflag,iter; uint32_t now = (uint32_t)time(NULL); + std::vector vopret; char maxflags[KOMODO_MAXPRICES]; uint245 bhash; double btcusd,btcgbp,btceur; uint32_t localbits[KOMODO_MAXPRICES],pricebits[KOMODO_MAXPRICES],prevbits[KOMODO_MAXPRICES],newprice; int32_t i,j,prevtime,maxflag,lag,lag2,lag3,n,errflag,iter; uint32_t now; + now = (uint32_t)time(NULL); if ( ASSETCHAINS_CBOPRET != 0 && nHeight > 0 ) { + bhash = block->GetHash(); GetOpReturnData(scriptPubKey,vopret); if ( vopret.size() >= PRICES_SIZEBIT0 ) { @@ -1815,7 +1831,7 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i } if ( j == KOMODO_LOCALPRICE_CACHESIZE ) { - komodo_queuelocalprice(1,block->GetHash(),i,prevbits[i]); + komodo_queuelocalprice(1,nHeight,block->nTime,bhash,i,prevbits[i]); break; } } @@ -1831,7 +1847,7 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i } if ( j == KOMODO_LOCALPRICE_CACHESIZE ) { - komodo_queuelocalprice(-1,block->GetHash(),i,prevbits[i]); + komodo_queuelocalprice(-1,nHeight,block->nTime,bhash,i,prevbits[i]); break; } } @@ -1849,6 +1865,11 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i } } } + if ( bhash == ExtremePrice.blockhash ) + { + fprintf(stderr,"approved a previously extreme price based on new data ht.%d vs %u vs %u\n",ExtremePrice.height,ExtremePrice.timestamp,(uint32_t)block.nTime); + memset(&ExtremePrice,0,sizeof(ExtremePrice)); + } return(0); } else fprintf(stderr,"wrong size %d vs %d, scriptPubKey size %d [%02x]\n",(int32_t)vopret.size(),(int32_t)Mineropret.size(),(int32_t)scriptPubKey.size(),scriptPubKey[0]); return(-1); @@ -2129,7 +2150,7 @@ void komodo_cbopretupdate(int32_t forceflag) { static uint32_t lasttime,lastcrypto,lastbtc,pending; static uint32_t pricebits[4],cryptoprices[KOMODO_MAXPRICES],forexprices[sizeof(Forex)/sizeof(*Forex)]; - int32_t size; uint32_t flags=0,now; + int32_t size; uint32_t flags=0,now; CBlockIndex *pindex; if ( forceflag != 0 && pending != 0 ) { while ( pending != 0 ) @@ -2187,6 +2208,16 @@ void komodo_cbopretupdate(int32_t forceflag) if ( (flags & 4) != 0 ) lastcrypto = now; memcpy(Mineropret.data(),PriceCache[0],size); + if ( ExtremePrice.dir != 0 && ExtremePrice.ind > 0 && ExtremePrice.ind < size/sizeof(uint32_t) && now < ExtremePrice.timestamp+3600 ) + { + if ( (ExtremePrice.dir > 0 && PriceCache[0][ExtremePrice.ind] >= ExtremePrice.pricebits) || (ExtremePrice.dir < 0 && PriceCache[0][ExtremePrice.ind] <= ExtremePrice.pricebits) ) + { + fprintf(stderr,"future price is close enough to allow approving previously rejected block ind.%d %u vs %u ht.%d\n",ExtremePrice.ind,PriceCache[0][ExtremePrice.ind],ExtremePrice.pricebits,height); + if ( (pindex= komodo_blockindex(ExtremePrice.blockhash)) != 0 ) + pindex->nStatus &= ~BLOCK_FAILED_MASK; + else fprintf(stderr,"couldnt find block.%s\n",ExtremePrice.blockhash.GetHex()); + } + } // high volatility still strands nodes so we need to check new prices to approve a stuck block // scan list of stuck blocks (one?) and auto reconsiderblock if it changed state From 43b18d52599059914b249e9c62a74c68cd02ec77 Mon Sep 17 00:00:00 2001 From: jl777 Date: Wed, 10 Apr 2019 02:47:17 -1100 Subject: [PATCH 32/35] Fix --- src/komodo_gateway.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/komodo_gateway.h b/src/komodo_gateway.h index 70a69ebc8..9afc9845c 100644 --- a/src/komodo_gateway.h +++ b/src/komodo_gateway.h @@ -1742,7 +1742,7 @@ void komodo_queuelocalprice(int32_t dir,int32_t height,uint32_t timestamp,uint25 int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,int32_t nHeight,CScript scriptPubKey) { int32_t testchain_exemption = 0; - std::vector vopret; char maxflags[KOMODO_MAXPRICES]; uint245 bhash; double btcusd,btcgbp,btceur; uint32_t localbits[KOMODO_MAXPRICES],pricebits[KOMODO_MAXPRICES],prevbits[KOMODO_MAXPRICES],newprice; int32_t i,j,prevtime,maxflag,lag,lag2,lag3,n,errflag,iter; uint32_t now; + std::vector vopret; char maxflags[KOMODO_MAXPRICES]; uint256 bhash; double btcusd,btcgbp,btceur; uint32_t localbits[KOMODO_MAXPRICES],pricebits[KOMODO_MAXPRICES],prevbits[KOMODO_MAXPRICES],newprice; int32_t i,j,prevtime,maxflag,lag,lag2,lag3,n,errflag,iter; uint32_t now; now = (uint32_t)time(NULL); if ( ASSETCHAINS_CBOPRET != 0 && nHeight > 0 ) { @@ -1867,7 +1867,7 @@ int32_t komodo_opretvalidate(const CBlock *block,CBlockIndex * const previndex,i } if ( bhash == ExtremePrice.blockhash ) { - fprintf(stderr,"approved a previously extreme price based on new data ht.%d vs %u vs %u\n",ExtremePrice.height,ExtremePrice.timestamp,(uint32_t)block.nTime); + fprintf(stderr,"approved a previously extreme price based on new data ht.%d vs %u vs %u\n",ExtremePrice.height,ExtremePrice.timestamp,(uint32_t)block->nTime); memset(&ExtremePrice,0,sizeof(ExtremePrice)); } return(0); @@ -2212,10 +2212,10 @@ void komodo_cbopretupdate(int32_t forceflag) { if ( (ExtremePrice.dir > 0 && PriceCache[0][ExtremePrice.ind] >= ExtremePrice.pricebits) || (ExtremePrice.dir < 0 && PriceCache[0][ExtremePrice.ind] <= ExtremePrice.pricebits) ) { - fprintf(stderr,"future price is close enough to allow approving previously rejected block ind.%d %u vs %u ht.%d\n",ExtremePrice.ind,PriceCache[0][ExtremePrice.ind],ExtremePrice.pricebits,height); + fprintf(stderr,"future price is close enough to allow approving previously rejected block ind.%d %u vs %u\n",ExtremePrice.ind,PriceCache[0][ExtremePrice.ind],ExtremePrice.pricebits); if ( (pindex= komodo_blockindex(ExtremePrice.blockhash)) != 0 ) pindex->nStatus &= ~BLOCK_FAILED_MASK; - else fprintf(stderr,"couldnt find block.%s\n",ExtremePrice.blockhash.GetHex()); + else fprintf(stderr,"couldnt find block.%s\n",ExtremePrice.blockhash.GetHex().c_str()); } } // high volatility still strands nodes so we need to check new prices to approve a stuck block From 2056c8727be31a38ae563bc207e4b3b8df26e1ae Mon Sep 17 00:00:00 2001 From: jl777 Date: Wed, 10 Apr 2019 05:14:54 -1100 Subject: [PATCH 33/35] Token peg ideas --- src/cc/pegs.cpp | 6 ++++++ src/cc/prices.cpp | 3 +++ 2 files changed, 9 insertions(+) diff --git a/src/cc/pegs.cpp b/src/cc/pegs.cpp index 00d76d8fd..38933ebdc 100644 --- a/src/cc/pegs.cpp +++ b/src/cc/pegs.cpp @@ -72,7 +72,13 @@ pegs CC is able to create a coin backed (by any supported coin with gateways CC Let us now consider how to enforce a peg onto a specific gateways CC token. If this can also be achieved, then a full DEX for all the different gateways CC supported coins can be created onto a single fiat denominated chain. + I think just having a pegscreate rpc call that binds an existing gateways create to a price CC syntax price will be almost enough to support this. Let us assume a USD stablechain and we have a BTC token, then pegscreate "BTCUSD, 1" + that will specify using the BTCUSD price, so now we need to create a based way to do tokenbid/tokenask. For a based price, the smoothed price is substituted. + There is the issue of the one day delay, so it might make sense to allow specific bid/ask to be based on some simple combinations of the three possible prices. it might even be possible to go a bit overboard and make a forth like syntax to define the dynamic price for a bid, which maybe at times wont be valid, like it is only valid if the three prices are within 1% of each other. But all that seems over complex and for initial release it can just use the mined, correlated or smoothed price, with some specified percentage offset + + Implementation notes: + make sure that fees and markers that can be sent to an unspendable address are sent to: RNdqHx26GWy9bk8MtmH1UiXjQcXE4RKK2P, this is the address for BOTS */ diff --git a/src/cc/prices.cpp b/src/cc/prices.cpp index ce257d33f..19194d16f 100644 --- a/src/cc/prices.cpp +++ b/src/cc/prices.cpp @@ -138,6 +138,9 @@ CBOPRET creates trustless oracles, which can be used for making a synthetic cash Another configuration is to send the 0.4% (or 0.2%) fees to a fee collection scriptPubKey (this is not currently implemented, but would be needed for systems that dont use -ac_perc to collect a global override) this requires adding new vouts Modification: in the event there is one price in the accumulator and one price on the stack at the end, then it is a (A - B) spread + + Monetizations should be sent to: RGsWqwFviaNJSbmgWi6338NL2tKkY7ZqKL + */ From 9b62776a8be938892056378868a4d2ff9f7d6d77 Mon Sep 17 00:00:00 2001 From: jl777 Date: Wed, 10 Apr 2019 05:27:06 -1100 Subject: [PATCH 34/35] -conflict --- src/rpc/crosschain.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/rpc/crosschain.cpp b/src/rpc/crosschain.cpp index 74ac53c44..0feb5173c 100644 --- a/src/rpc/crosschain.cpp +++ b/src/rpc/crosschain.cpp @@ -413,9 +413,9 @@ UniValue selfimport(const UniValue& params, bool fHelp) return result; } -<<<<<<< HEAD bool GetNotarisationNotaries(uint8_t notarypubkeys[64][33], int8_t &numNN, const std::vector &vin, std::vector &NotarisationNotaries); -======= + + UniValue importdual(const UniValue& params, bool fHelp) { UniValue result(UniValue::VOBJ); @@ -749,7 +749,6 @@ UniValue importgatewaydumpprivkey(const UniValue& params, bool fHelp) //} return(ImportGatewayDumpPrivKey(bindtxid,vchSecret)); } ->>>>>>> FSM UniValue getNotarisationsForBlock(const UniValue& params, bool fHelp) { From 0e2969debb70a41c1ab24340ee1863d7fb5da179 Mon Sep 17 00:00:00 2001 From: blackjok3r Date: Thu, 11 Apr 2019 14:28:24 +0800 Subject: [PATCH 35/35] notarystats.py update to official regions/stop height. --- src/notarystats.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/notarystats.py b/src/notarystats.py index 0e7673833..49713b6c3 100755 --- a/src/notarystats.py +++ b/src/notarystats.py @@ -53,11 +53,11 @@ def def_credentials(chain): rpc = def_credentials('KMD') pp = pprint.PrettyPrinter(indent=2) -notarynames = [ "0dev1_jl777", "0dev2_kolo", "0dev3_kolo", "0dev4_decker", "a-team_SH", "artik_AR", "artik_EU", "artik_NA", "artik_SH", "badass_EU", "badass_NA", "batman_AR", "batman_SH", "ca333_EU", "chainmakers_EU", "chainmakers_NA", "chainstrike_SH", "cipi_AR", "cipi_NA", "crackers_EU", "crackers_NA", "dwy_EU", "emmanux_SH", "etszombi_EU", "fullmoon_AR", "fullmoon_NA", "fullmoon_SH", "goldenman_EU", "indenodes_AR", "indenodes_EU", "indenodes_NA", "indenodes_SH", "jackson_AR", "jeezy_EU", "karasugoi_NA", "komodoninja_EU", "komodoninja_SH", "komodopioneers_SH", "libscott_SH", "lukechilds_AR", "madmax_AR", "meshbits_AR", "meshbits_SH", "metaphilibert_AR", "metaphilibert_SH", "patchkez_SH", "pbca26_NA", "peer2cloud_AR", "peer2cloud_SH", "polycryptoblog_NA", "hyper_AR", "hyper_EU", "hyper_SH", "hyper_NA", "popcornbag_AR", "popcornbag_NA", "alien_AR", "alien_EU", "thegaltmines_NA", "titomane_AR", "titomane_EU", "titomane_SH", "webworker01_NA", "xrobesx_NA" ] +notarynames = [ "0dev1_jl777", "0dev2_kolo", "0dev3_kolo", "0dev4_decker_AR", "a-team_SH", "artik_AR", "artik_EU", "artik_NA", "artik_SH", "badass_EU", "badass_NA", "batman_AR", "batman_SH", "ca333", "chainmakers_EU", "chainmakers_NA", "chainstrike_SH", "cipi_AR", "cipi_NA", "crackers_EU", "crackers_NA", "dwy_EU", "emmanux_SH", "etszombi_EU", "fullmoon_AR", "fullmoon_NA", "fullmoon_SH", "goldenman_EU", "indenodes_AR", "indenodes_EU", "indenodes_NA", "indenodes_SH", "jackson_AR", "jeezy_EU", "karasugoi_NA", "komodoninja_EU", "komodoninja_SH", "komodopioneers_SH", "libscott_SH", "lukechilds_AR", "madmax_AR", "meshbits_AR", "meshbits_SH", "metaphilibert_AR", "metaphilibert_SH", "patchkez_SH", "pbca26_NA", "peer2cloud_AR", "peer2cloud_SH", "polycryptoblog_NA", "hyper_AR", "hyper_EU", "hyper_SH", "hyper_NA", "popcornbag_AR", "popcornbag_NA", "alien_AR", "alien_EU", "thegaltmines_NA", "titomane_AR", "titomane_EU", "titomane_SH", "webworker01_NA", "xrobesx_NA" ] notaries = 64 * [0] startheight = 821657 #Second time filter for assetchains (block 821657) for KMD its 814000 -stopheight = rpc.getblockcount() # @kolo what height does season end?! +stopheight = 1307200 for i in range(startheight,stopheight): ret = rpc.getNotarisationsForBlock(i) KMD = ret['KMD']