Merge pull request #36 from jl777/jl777

Jl777
This commit is contained in:
blackjok3rtt
2019-03-22 09:16:58 +08:00
committed by GitHub
143 changed files with 11851 additions and 2417 deletions

11
.gitignore vendored
View File

@@ -132,6 +132,11 @@ src/cc/rogue/rogue
src/cc/rogue/rogue.so
src/cc/rogue/test.zip
src/checkfile
src/foo.zip
src/log
src/rogue.530623577502174316.0
@@ -139,11 +144,6 @@ src/rogue.530623577502174316.pack
src/rogue.530623577502174316.player
src/checkfile
src/log
src/foo.zip
src/cc/rogue/config.h
@@ -154,3 +154,4 @@ src/ROGUE.conf
src/rogue.scr
src/cc/rogue/confdefs.h
src/cc/rogue/x64

View File

@@ -71,6 +71,10 @@ build:windows:
- cp src/komodod.exe
src/komodo-cli.exe
src/komodo-tx.exe
src/cc/rogue/rogue.exe
zcutil/fetch-params.bat
src/cc/rogue/x86_64-w64-mingw32/bin/libcurl-4.dll
src/cc/rogue/x86_64-w64-mingw32/bin/libncursesw6.dll
${PACKAGE_DIR_WINDOWS}
- zip -r ${PACKAGE_DIR_WINDOWS}.zip ${PACKAGE_DIR_WINDOWS}
- md5sum ${AGAMA_ARTIFACTS_WINDOWS} > ${AGAMA_ARTIFACTS_WINDOWS_CHECKSUM}
@@ -91,6 +95,7 @@ build:macos:
key: "${CI_JOB_NAME}${CI_COMMIT_REF_NAME}"
paths:
- depends/built
allow_failure: true
script:
- zcutil/build-mac.sh -j$(sysctl -n hw.physicalcpu)
- ./makeRelease.sh ${PACKAGE_DIR_MACOS}

View File

@@ -71,16 +71,32 @@ cd komodo
#This can take some time.
```
#### OSX
Ensure you have [brew](https://brew.sh) and the command line tools installed (comes automatically with XCode) and run:
Ensure you have [brew](https://brew.sh) and Command Line Tools installed.
```shell
brew update && brew install gcc@6
# Install brew
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
# Install Xcode, opens a pop-up window to install CLT without installing the entire Xcode package
xcode-select --install
# Update brew and install dependencies
brew update
brew upgrade
brew tap discoteq/discoteq; brew install flock
brew install autoconf autogen automake
brew install gcc@6
brew install binutils
brew install protobuf
brew install coreutils
brew install wget
# Clone the Komodo repo
git clone https://github.com/komodoplatform/komodo --branch master --single-branch
# Change master branch to other branch you wish to compile
cd komodo
./zcutil/fetch-params.sh
# -j8 = using 8 threads for the compilation - replace 8 with number of threads you want to use
./zcutil/build-mac.sh -j8
#This can take some time.
# This can take some time.
```
#### Windows

View File

@@ -1,8 +1,9 @@
package=boost
$(package)_version=1_66_0
$(package)_download_path=https://dl.bintray.com/boostorg/release/1.66.0/source
$(package)_file_name=$(package)_$($(package)_version).tar.bz2
$(package)_sha256_hash=5721818253e6a0989583192f96782c4a98eb6204965316df9f5ad75819225ca9
$(package)_file_name=$(package)_$($(package)_version).tar.bz2
define $(package)_set_vars
$(package)_config_opts_release=variant=release

View File

@@ -1,21 +1,21 @@
ifeq ($(host_os),mingw32)
$(package)_version=4.2.2-1
$(package)_version=4.3.1
$(package)_download_path=https://github.com/ca333/libzmq/archive
$(package)_download_file=v$($(package)_version).tar.gz
$(package)_file_name=libzmq-$($(package)_version).tar.gz
$(package)_sha256_hash=0e225b85ce11be23bf7eb7d3f25c6686728bf30d5c31f61c12d37bb646c69962
$(package)_sha256_hash=cb8ebe5b60dadeb526745610d6237f05a98aba287114d8991dad1fa14f4be354
define $(package)_set_vars
$(package)_build_env+=
$(package)_config_opts=--enable-shared=false --enable-static --host=x86_64-w64-mingw32
$(package)_config_opts_mingw32=--enable-shared=false --enable-static --host=x86_64-w64-mingw32
$(package)_config_opts_mingw32=--enable-shared=false --enable-static --prefix=$(host_prefix) --host=x86_64-w64-mingw32 -disable-curve
$(package)_cflags=-Wno-error -Wall -Wno-pedantic-ms-format -DLIBCZMQ_EXPORTS -DZMQ_DEFINED_STDINT -lws2_32 -liphlpapi -lrpcrt4
$(package)_conf_tool=./configure
endef
else
package=zeromq
$(package)_version=4.3.1
$(package)_download_path=https://github.com/zeromq/libzmq/releases/download/v$($(package)_version)/
$(package)_download_path=https://github.com/zeromq/libzmq/releases/download/v$($(package)_version)
$(package)_file_name=$(package)-$($(package)_version).tar.gz
$(package)_sha256_hash=bcbabe1e2c7d0eec4ed612e10b94b112dd5f06fcefa994a0c79a45d835cd21eb

View File

@@ -0,0 +1,58 @@
Komodo specific changelog:
- add CC functionality and bugfixes
- set sapling activation
- change z-addr prefix byte
- blocksize increased from 2MB to 4 MB
- transaction size increased from 100KB to 200KB
Sapling related changelog:
- Decoupled Spend Authority
- Improved Performance for Shielded Transactions (using sapling instead of sprout)
- transaction format changed
Alex Morcos (1): Output line to debug.log when IsInitialBlockDownload latches to false
Ariel Gabizon (1): Extend Joinsplit tests to Groth
Charlie OKeefe (1): Remove extra slash from lockfile path
Cory Fields (1): crypter: shuffle Makefile so that crypto can be used by the wallet
Daira Hopwood (1): Support testnet rollback.
Daniel Cousens (2): move rpc* to rpc/ rpc: update inline comments to refer to new file paths
Dimitris Apostolou (1): Fix typos
Duke Leto (3): Fix absurd fee bug reported in #3281, with tests Update comment as per @arielgabizon Improve error message
Eirik Ogilvie-Wigley (24): Add more options when asserting in RPC tests Add change indicator for notes Fix test broken by change indicator Rename note data to include sprout Remove redundant curly braces Consolidate for loops Add out point for sapling note data Add sapling note data and map Decrement sapling note witnesses Clear sapling witness cache Extract method for copying previous witnesses Extract methods for incrementing witnesses Extract method for incrementing witness heights Pass sapling merkle tree when incrementing witnesses Increment sapling note witnesses Rename sprout specific methods Remove extra indentation Add getter and setter for sapling note data and update tests Add parameter for version in GetValidReceive Rename Merkle Trees to include sprout or sapling Rename Witnesses to include sprout or sapling Rename test objects to include sprout or sapling Only include the change field if we have a spending key Fix assertion and comment
Gregory Maxwell (2): IBD check uses minimumchain work instead of checkpoints. IsInitialBlockDownload no longer uses header-only timestamps.
Jack Grigg (41): Add some more checkpoints, up to the 1.1.0 release Add Sapling support to z_validateaddress Update payment-api.md with type field of z_validateaddress Alter SaplingNote::nullifier() to take a SaplingFullViewingKey Expose note position in IncrementalMerkleWitness TransactionBuilder with support for creating Sapling-only transactions TransactionBuilder: Check that all anchors in a transaction are identical Formatting test: Move ECC_Start() call into src/gtest/main.cpp TransactionBuilder: Add support for transparent inputs and outputs TransactionBuilder: Add change output to transaction TransactionBuilder: Make fee configurable Rename xsk to expsk Implement CKeyStore::GetSaplingPaymentAddresses() Raise the 90-character limit on Bech32 encodings Add Sapling support to z_getnewaddress and z_listaddresses Fix block hash for checkpoint at height 270000 Formatting test: Deduplicate logic in wallet_addresses RPC test test: Another assert in wallet_zkeys_tests.store_and_load_sapling_zkeys test: Fix permissions of wallet_addresses test: Update rpc_wallet_z_importexport to account for Sapling changes Rename DecryptSpendingKey -> DecryptSproutSpendingKey Rename CryptedSpendingKeyMap -> CryptedSproutSpendingKeyMap Add Sapling decryption check to CCryptoKeyStore::Unlock() Check for unencrypted Sapling keys in CCryptoKeyStore::SetCrypted() Remove outdated comment Add CWallet::AddCryptedSaplingSpendingKey() hook Pass SaplingPaymentAddress to store through the CKeyStore Rename SpendingKeyMap -> SproutSpendingKeyMap Rename SerializedSize -> SerializedSproutSize Rename ViewingKey -> SproutViewingKey Formatting nits Rename *SpendingKey -> *SproutSpendingKey chainparams: Add BIP 44 coin type (as registered in SLIP 44) Upgrade Rust to 1.28.0 stable Adjust Makefile so that common can be used by the wallet Move RewindBlockIndex log message inside rewindLength check test: gtest for Sapling encoding and decoding test: Use regtest in key_tests/zs_address_test Disable Sapling features on mainnet
Jay Graber (13): Add Sapling Add/Have/Get to keystore Add SaplingIncomingViewingKeys map, SaplingFullViewingKey methods Add StoreAndRetrieveSaplingSpendingKey test Change default_address to return SaplingPaymentAddr and not boost::optional Add crypted keystore sapling add key Discard sk if ivk == 0 Add Sapling support to z_exportkey Add Sapling support to z_importkey Add Sapling to rpc_wallet_z_importexport test Refactor into visitors and throw errors for invalid key or address. Take expiryheight as param to createrawtransaction Add Sapling have/get sk crypter overrides Add Sapling keys to CCryptoKeyStore::EncryptKeys
Jonas Schnelli (2): [RPC, Wallet] Move RPC dispatch table registration to wallet/ code Fix test_bitcoin circular dependency issue
Kaz Wesley (1): IsInitialBlockDownload: usually avoid locking
Larry Ruane (4): Disable libsnark debug logging in Boost tests add extra help how to enable experimental features Add call to sync_all() after (z_sendmany, wait) don't ban peers when loading pre-overwinter blocks
Pejvan (2): Update README.md Update README.md
Richard Littauer (1): docs(LICENSE): update license year to 2018
Sean Bowe (21): Update librustzcash Implementation of Sapling in-band secret distribution. Swap types in OutputDescription to use new NoteEncryption interfaces. Prevent nonce reuse in Sapling note encryption API. Add get_esk() function to Sapling note encryption. Minor edits Decryption and tests of note/outgoing encryption. Update librustzcash and sapling-crypto. Fix bug in return value. Ensure sum of valueBalance and all vpub_new's does not exceed MAX_MONEY inside of CheckTransactionWithoutProofVerification. Move extern params to beginning of test_checktransaction. Relocate ECC_Start() to avoid test failures. Don't call ECC_Start/ECC_Stop outside the test harness. Make changes to gtest ECC behavior suggested by @str4d. Check the hash of the (Sapling+) zk-SNARK parameters during initialization. Switch to use the official Sapling parameters. make-release.py: Versioning changes for 2.0.0-rc1. make-release.py: Updated manpages for 2.0.0-rc1. make-release.py: Updated release notes and changelog for 2.0.0-rc1. Always write the empty root down as the best root, since we may roll back. Sapling mainnet activation height
Simon Liu (11): Add encryption of SaplingNotePlaintext and SaplingOutgoingPlaintext classes. Update and fix per review comments, the test for absurd fee. Minor update to address nits in review. Implement Sapling note decryption using full viewing key. Rename AttemptSaplingEncDecryptionUsingFullViewingKey and use function overloading. Only check for a valid Sapling anchor after Sapling activation. Clean up for rebase: rename mapNoteData to mapSproutNoteData. Clean up help messages for RPC createrawtransaction. Add tests for expiryheight parameter of RPC createrawtransaction. make-release.py: Versioning changes for 2.0.0. make-release.py: Updated manpages for 2.0.0.
Wladimir J. van der Laan (2): Make max tip age an option instead of chainparam rpc: Register calls where they are defined
kozyilmaz (1): Add -Wl,-pie linker option for macOS and use it instead of -pie
mdr0id (1): Fix minor references to auto-senescence in code

View File

@@ -11,6 +11,8 @@ export BITCOIND=${REAL_BITCOIND}
#Run the tests
testScripts=(
'dpow.py'
'dpowconfs.py'
'ac_private.py'
'verushash.py'
'paymentdisclosure.py'

View File

@@ -31,7 +31,8 @@ class CryptoconditionsChannelsTest(CryptoconditionsTestFramework):
result = rpc.channelsaddress(self.pubkey)
assert_success(result)
# test that additional CCaddress key is returned
for x in ['myCCaddress', 'ChannelsCCaddress', 'Channelsmarker', 'myaddress', 'CCaddress']:
for x in ['ChannelsCC1of2TokensAddress', 'myCCAddress(Channels)', 'ChannelsCC1of2Address', 'myAddress', \
'myCCaddress', 'ChannelsNormalAddress', 'PubkeyCCaddress(Channels)', 'ChannelsCCAddress']:
assert_equal(result[x][0], 'R')
# getting empty channels list

View File

@@ -24,15 +24,19 @@ class CryptoconditionsDiceTest(CryptoconditionsTestFramework):
result = rpc1.getbalance()
assert_greater_than(result, 100000)
dice = rpc.diceaddress()
assert_equal(dice['result'], 'success')
for x in ['myCCaddress', 'DiceCCaddress', 'Dicemarker', 'myaddress']:
assert_equal(dice[x][0], 'R')
result = rpc.diceaddress()
for x in result.keys():
print(x+": "+str(result[x]))
assert_equal(result['result'], 'success')
for x in ['myCCaddress', 'DiceCCAddress', 'myaddress']:
assert_equal(result[x][0], 'R')
dice = rpc.diceaddress(self.pubkey)
assert_equal(dice['result'], 'success')
for x in ['myCCaddress', 'DiceCCaddress', 'Dicemarker', 'myaddress', 'CCaddress']:
assert_equal(dice[x][0], 'R')
result = rpc.diceaddress(self.pubkey)
for x in result.keys():
print(x+": "+str(result[x]))
assert_equal(result['result'], 'success')
for x in ['myCCaddress', 'DiceCCAddress', 'myaddress', 'DiceCCTokensAddress', 'DiceNormalAddress']:
assert_equal(result[x][0], 'R')
# no dice created yet
result = rpc.dicelist()

View File

@@ -24,16 +24,20 @@ class CryptoconditionsFaucetTest(CryptoconditionsTestFramework):
assert_greater_than(result['balance'], 0.0)
balance = result['balance']
faucet = rpc.faucetaddress()
assert_equal(faucet['result'], 'success')
result = rpc.faucetaddress()
assert_equal(result['result'], 'success')
for x in result.keys():
print(x+": "+str(result[x]))
# verify all keys look like valid AC addrs, could be better
for x in ['myCCaddress', 'FaucetCCaddress', 'Faucetmarker', 'myaddress']:
assert_equal(faucet[x][0], 'R')
for x in ['myCCaddress', 'FaucetCCTokensAddress', 'FaucetNormalAddress', 'myaddress']:
assert_equal(result[x][0], 'R')
result = rpc.faucetaddress(self.pubkey)
assert_success(result)
for x in result.keys():
print(x+": "+str(result[x]))
# test that additional CCaddress key is returned
for x in ['myCCaddress', 'FaucetCCaddress', 'Faucetmarker', 'myaddress', 'CCaddress']:
for x in ['myCCaddress', 'FaucetCCTokensAddress', 'FaucetNormalAddress', 'myaddress']:
assert_equal(result[x][0], 'R')
# no funds in the faucet yet

View File

@@ -20,16 +20,16 @@ class CryptoconditionsHeirTest(CryptoconditionsTestFramework):
rpc = self.nodes[0]
rpc1 = self.nodes[1]
result = rpc.heiraddress()
result = rpc.heiraddress('')
assert_success(result)
# verify all keys look like valid AC addrs, could be better
for x in ['myCCaddress', 'HeirCCaddress', 'Heirmarker', 'myaddress']:
for x in ['HeirNormalAddress', 'HeirCCTokensAddress', 'myaddress', 'myCCaddress', 'HeirCCAddress']:
assert_equal(result[x][0], 'R')
result = rpc.heiraddress(self.pubkey)
assert_success(result)
# test that additional CCaddress key is returned
for x in ['myCCaddress', 'HeirCCaddress', 'Heirmarker', 'myaddress', 'CCaddress']:
for x in ['HeirNormalAddress', 'myCCaddress', 'myaddress', 'HeirCC1of2Address', 'HeirCCAddress', 'HeirCC1of2TokensAddress']:
assert_equal(result[x][0], 'R')
# getting empty heir list

View File

@@ -22,12 +22,12 @@ class CryptoconditionsOraclesTest(CryptoconditionsTestFramework):
result = rpc.oraclesaddress()
assert_success(result)
for x in ['OraclesCCaddress', 'Oraclesmarker', 'myCCaddress', 'myaddress']:
for x in ['myCCaddress', 'OraclesCCAddress', 'OraclesNormalAddress', 'myaddress', 'OraclesCCTokensAddress']:
assert_equal(result[x][0], 'R')
result = rpc.oraclesaddress(self.pubkey)
assert_success(result)
for x in ['OraclesCCaddress', 'Oraclesmarker', 'myCCaddress', 'myaddress']:
for x in ['myCCaddress', 'OraclesCCAddress', 'OraclesNormalAddress', 'myaddress', 'OraclesCCTokensAddress']:
assert_equal(result[x][0], 'R')
# there are no oracles created yet

View File

@@ -15,13 +15,15 @@ from cryptoconditions import assert_success, assert_error, generate_random_strin
class CryptoconditionsRewardsTest(CryptoconditionsTestFramework):
def run_rewards_tests(self):
rpc = self.nodes[0]
result = rpc.rewardsaddress()
for x in ['RewardsCCaddress', 'myCCaddress', 'Rewardsmarker', 'myaddress']:
for x in ['myCCaddress', 'myaddress', 'RewardsCCAddress', 'RewardsCCTokensAddress', 'RewardsNormalAddress']:
assert_equal(result[x][0], 'R')
result = rpc.rewardsaddress(self.pubkey)
for x in ['RewardsCCaddress', 'myCCaddress', 'Rewardsmarker', 'myaddress', 'CCaddress']:
for x in ['myCCaddress', 'myaddress', 'RewardsCCAddress', 'RewardsCCTokensAddress', 'RewardsNormalAddress']:
assert_equal(result[x][0], 'R')
# no rewards yet

View File

@@ -21,22 +21,22 @@ class CryptoconditionsTokenTest(CryptoconditionsTestFramework):
result = rpc.tokenaddress()
assert_success(result)
for x in ['TokensCCaddress', 'myCCaddress', 'Tokensmarker', 'myaddress']:
for x in ['TokensCCAddress', 'myCCaddress', 'myCCAddress(Tokens)', 'myaddress', 'TokensNormalAddress']:
assert_equal(result[x][0], 'R')
result = rpc.tokenaddress(self.pubkey)
assert_success(result)
for x in ['TokensCCaddress', 'myCCaddress', 'Tokensmarker', 'myaddress', 'CCaddress']:
for x in ['TokensCCAddress', 'myCCaddress', 'myCCAddress(Tokens)', 'myaddress', 'TokensNormalAddress']:
assert_equal(result[x][0], 'R')
result = rpc.assetsaddress()
assert_success(result)
for x in ['AssetsCCaddress', 'myCCaddress', 'Assetsmarker', 'myaddress']:
for x in ['AssetsCCAddress', 'myCCaddress', 'myCCAddress(Assets)', 'myaddress', 'AssetsNormalAddress']:
assert_equal(result[x][0], 'R')
result = rpc.assetsaddress(self.pubkey)
assert_success(result)
for x in ['AssetsCCaddress', 'myCCaddress', 'Assetsmarker', 'myaddress', 'CCaddress']:
for x in ['AssetsCCAddress', 'myCCaddress', 'myCCAddress(Assets)', 'myaddress', 'AssetsNormalAddress']:
assert_equal(result[x][0], 'R')
# there are no tokens created yet
@@ -61,7 +61,7 @@ class CryptoconditionsTokenTest(CryptoconditionsTestFramework):
assert_equal(result[0], tokenid)
# there are no token orders yet
result = rpc.tokenorders()
result = rpc.tokenorders(tokenid)
assert_equal(result, [])
# getting token balance for non existing tokenid
@@ -117,7 +117,7 @@ class CryptoconditionsTokenTest(CryptoconditionsTestFramework):
tokenask = rpc.tokenask("100", tokenid, "7.77")
tokenaskhex = tokenask['hex']
tokenaskid = self.send_and_mine(tokenask['hex'], rpc)
result = rpc.tokenorders()
result = rpc.tokenorders(tokenid)
order = result[0]
assert order, "found order"
@@ -136,7 +136,7 @@ class CryptoconditionsTokenTest(CryptoconditionsTestFramework):
assert txid, "found txid"
# should be no token orders
result = rpc.tokenorders()
result = rpc.tokenorders(tokenid)
assert_equal(result, [])
# checking ask cancellation
@@ -157,7 +157,7 @@ class CryptoconditionsTokenTest(CryptoconditionsTestFramework):
# from valid node
cancel = rpc.tokencancelask(tokenid, testorderid)
self.send_and_mine(cancel["hex"], rpc)
result = rpc.tokenorders()
result = rpc.tokenorders(tokenid)
assert_equal(result, [])
@@ -184,7 +184,7 @@ class CryptoconditionsTokenTest(CryptoconditionsTestFramework):
tokenbid = rpc.tokenbid("100", tokenid, "10")
tokenbidhex = tokenbid['hex']
tokenbidid = self.send_and_mine(tokenbid['hex'], rpc)
result = rpc.tokenorders()
result = rpc.tokenorders(tokenid)
order = result[0]
assert order, "found order"
@@ -203,7 +203,7 @@ class CryptoconditionsTokenTest(CryptoconditionsTestFramework):
assert txid, "found txid"
# should be no token orders
result = rpc.tokenorders()
result = rpc.tokenorders(tokenid)
assert_equal(result, [])
# checking bid cancellation
@@ -220,7 +220,7 @@ class CryptoconditionsTokenTest(CryptoconditionsTestFramework):
# from valid node
cancel = rpc.tokencancelbid(tokenid, testorderid)
self.send_and_mine(cancel["hex"], rpc)
result = rpc.tokenorders()
result = rpc.tokenorders(tokenid)
assert_equal(result, [])
# invalid token transfer amount (have to add status to CC code!)

151
qa/rpc-tests/dpowconfs.py Executable file
View File

@@ -0,0 +1,151 @@
#!/usr/bin/env python2
# Copyright (c) 2018 The Hush developers
# Copyright (c) 2019 The SuperNET developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
import time
class DPoWConfsTest(BitcoinTestFramework):
def debug_info(self):
rpc = self.nodes[0]
print "-- DEBUG --"
getinfo = rpc.getinfo()
getwalletinfo = rpc.getwalletinfo()
listreceivedbyaddress = rpc.listreceivedbyaddress()
print "notarized=", getinfo['notarized'], " blocks=", getinfo['blocks']
#print "getinfo=", getinfo
print "balance=", getwalletinfo['balance']
#print "getwalletinfo=", getwalletinfo
print "listreceivedbyaddress=", listreceivedbyaddress
print "-- DEBUG --"
def setup_chain(self):
self.num_nodes = 1
print("Initializing DPoWconfs test directory "+self.options.tmpdir)
initialize_chain_clean(self.options.tmpdir, self.num_nodes)
def setup_network(self):
print("Setting up network...")
self.nodes = []
self.is_network_split = False
self.addr = "RWPg8B91kfK5UtUN7z6s6TeV9cHSGtVY8D"
self.pubkey = "02676d00110c2cd14ae24f95969e8598f7ccfaa675498b82654a5b5bd57fc1d8cf"
self.nodes = start_nodes( self.num_nodes, self.options.tmpdir,
extra_args=[[
'-ac_name=REGTEST',
'-conf='+self.options.tmpdir+'/node0/REGTEST.conf',
'-port=64367',
'-rpcport=64368',
'-regtest',
'-addressindex=1',
'-spentindex=1',
'-ac_supply=5555555',
'-ac_reward=10000000000000',
#'-pubkey=' + self.pubkey,
'-ac_cc=2',
'-whitelist=127.0.0.1',
'-debug',
'--daemon',
'-rpcuser=rt',
'-rpcpassword=rt'
]]
)
self.sync_all()
def run_test(self):
rpc = self.nodes[0]
# 98 is notarized, next will be 105. Must mine at least 101
# blocks for 100 block maturity rule
blockhashes = rpc.generate(101)
# block 98, this is 0 indexed
notarizedhash = blockhashes[97]
self.debug_info()
taddr = rpc.getnewaddress()
txid = rpc.sendtoaddress(taddr, 5.55)
# blocks 102,103
rpc.generate(2)
self.debug_info()
info = rpc.getinfo()
print "notarizedhash=", notarizedhash, "\n"
print "info[notarizedhash]", info['notarizedhash'], "\n"
assert_equal( info['notarizedhash'], notarizedhash)
result = rpc.listunspent()
# this xtn has 2 raw confs, but not in a notarized block,
# so dpowconfs holds it at 1
for res in result:
if (res['address'] == taddr and res['generated'] == 'false'):
assert_equal( result[0]['confirmations'], 1 )
assert_equal( result[0]['rawconfirmations'], 2 )
# we will now have 3 rawconfs but confirmations=1 because not notarized
# block 104
rpc.generate(1)
self.debug_info()
minconf = 2
result = rpc.listreceivedbyaddress(minconf)
print "listreceivedbyaddress(2)=", result, "\n"
# nothing is notarized, so we should see no results for minconf=2
assert len(result) == 0
print "getreceivedaddress"
received = rpc.getreceivedbyaddress(taddr, minconf)
assert_equal( received, 0.00000000)
#received = rpc.getreceivedbyaddress(taddr)
#assert_equal( received, "5.55000000")
taddr = rpc.getnewaddress()
zaddr = rpc.z_getnewaddress()
# should get insufficient funds error
recipients = [ { "amount" : Decimal('4.20'), "address" : zaddr } ]
txid = rpc.z_sendmany( taddr, recipients, minconf)
# generate a notarized block, block 105 and block 106
# only generating the notarized block seems to have
# race conditions about whether the block is notarized
txids = rpc.generate(2)
self.debug_info()
getinfo = rpc.getinfo()
# try to allow notarization data to update
print "Sleeping"
while (getinfo['blocks'] != 106) or (getinfo['notarized'] != 105):
printf(".")
time.sleep(1)
getinfo = rpc.getinfo()
# make sure this block was notarized as we expect
#assert_equal(getinfo['blocks'], getinfo['notarized'])
#assert_equal(getinfo['notarizedhash'], txids[0])
result = rpc.listreceivedbyaddress(minconf)
print "listreceivedbyaddress(2)=", result
assert_equal( len(result), 1, 'got one xtn with minconf=2' )
# verify we see the correct dpowconfs + rawconfs
assert_greater_than( result[0]['confirmations'], 1)
assert_greater_than( result[0]['rawconfirmations'], 1)
print "listtransactions"
xtns = rpc.listtransactions()
# verify this rpc agrees with listreceivedbyaddress
assert_greater_than(xtns[0]['confirmations'], 1)
assert_greater_than(xtns[0]['rawconfirmations'], 1)
print "getreceivedaddress"
received = rpc.getreceivedbyaddress(taddr, minconf)
assert_equal( "%.8f" % received, "5.55000000")
received = rpc.getreceivedbyaddress(taddr)
assert_equal( "%.8f" % received, "5.55000000")
if __name__ == '__main__':
DPoWConfsTest().main()

View File

@@ -1,9 +1,7 @@
# Copyright (c) 2014 The Bitcoin Core developers
# Copyright (c) 2018 The SuperNET developers
# Copyright (c) 2018-2019 The SuperNET developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
#
# Helpful routines for regression testing
#
@@ -415,10 +413,16 @@ def assert_true(condition, message = ""):
def assert_false(condition, message = ""):
assert_true(not condition, message)
# assert thing2 > thing1
def assert_greater_than(thing1, thing2):
if thing1 <= thing2:
raise AssertionError("%s <= %s"%(str(thing1),str(thing2)))
# assert thing2 >= thing1
def assert_greater_than_or_equal(thing1, thing2):
if thing1 < thing2:
raise AssertionError("%s < %s"%(str(thing1),str(thing2)))
def assert_raises(exc, fun, *args, **kwds):
try:
fun(*args, **kwds)

View File

@@ -204,6 +204,7 @@ BITCOIN_CORE_H = \
mruset.h \
net.h \
netbase.h \
notaries_staked.h \
noui.h \
paymentdisclosure.h \
paymentdisclosuredb.h \
@@ -311,6 +312,7 @@ libbitcoin_server_a_SOURCES = \
chain.cpp \
checkpoints.cpp \
crosschain.cpp \
crosschain_authority.cpp \
crypto/haraka.h \
crypto/haraka_portable.h \
crypto/verus_hash.h \
@@ -325,6 +327,7 @@ libbitcoin_server_a_SOURCES = \
metrics.h \
miner.cpp \
net.cpp \
notaries_staked.cpp \
noui.cpp \
notarisationdb.cpp \
paymentdisclosure.cpp \
@@ -487,6 +490,8 @@ libbitcoin_common_a_SOURCES = \
script/sign.cpp \
script/standard.cpp \
transaction_builder.cpp \
cc/CCtokensOpRet.cpp \
cc/CCutilbits.cpp \
$(BITCOIN_CORE_H) \
$(LIBZCASH_H)

3
src/ac/ilien Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/bash
./komodo-cli -ac_name=ILN $1 $2 $3 $4 $5 $6

2
src/ac/iln Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/bash
./komodo-cli -ac_name=ILN $1 $2 $3 $4 $5 $6

2
src/ac/our Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/bash
./komodo-cli -ac_name=OUR $1 $2 $3 $4 $5 $6

View File

@@ -64,13 +64,10 @@
"ac_name": "MESH",
"ac_supply": "1000007"
},
{
"ac_name": "MNZ",
"ac_supply": "257142858"
},
{
"ac_name": "AXO",
"ac_supply": "200000000"
"ac_supply": "200000000",
"ac_ccactivate": "130000"
},
{
"ac_name": "ETOMIC",
@@ -182,7 +179,7 @@
"190.114.254.104"
]
},
{
{
"ac_name": "DION",
"ac_supply": "3900000000",
"ac_reward": "22260000000",
@@ -238,7 +235,14 @@
"addnode": [
"51.255.195.65",
"217.182.129.38",
"95.216.150.177"
]
}
"37.187.225.231"
]
},
{
"ac_name": "ILN",
"ac_supply": "10000000000",
"ac_cc": "2",
"addnode": ["51.75.122.83"]
}
]

View File

@@ -20,8 +20,7 @@ echo $pubkey
./komodod -pubkey=$pubkey -ac_name=KV -ac_supply=1000000 -addnode=78.47.196.146 $1 &
./komodod -pubkey=$pubkey -ac_name=CEAL -ac_supply=366666666 -addnode=78.47.196.146 $1 &
./komodod -pubkey=$pubkey -ac_name=MESH -ac_supply=1000007 -addnode=78.47.196.146 $1 &
./komodod -pubkey=$pubkey -ac_name=MNZ -ac_supply=257142858 -addnode=51.15.138.138 $1 &
./komodod -pubkey=$pubkey -ac_name=AXO -ac_supply=200000000 -addnode=78.47.196.146 &
./komodod -pubkey=$pubkey -ac_name=AXO -ac_supply=200000000 -ac_ccactivate=130000 -addnode=78.47.196.146 &
./komodod -pubkey=$pubkey -ac_name=ETOMIC -ac_supply=100000000 -addnode=78.47.196.146 &
./komodod -pubkey=$pubkey -ac_name=BTCH -ac_supply=20998641 -addnode=78.47.196.146 &
./komodod -pubkey=$pubkey -ac_name=BEER -ac_supply=100000000 -addnode=78.47.196.146 &
@@ -46,3 +45,6 @@ echo $pubkey
./komodod -pubkey=$pubkey -ac_name=DION -ac_supply=3900000000 -ac_reward=22260000000 -ac_staked=100 -ac_cc=1 -ac_end=4300000000 -addnode=51.75.124.34 &
./komodod -pubkey=$pubkey -ac_name=ZEX -ac_cc=2 -ac_founders=1 -ac_halving=525600 -ac_reward=13000000000 -ac_pubkey=039d4a50cc70d1184e462a22edb3b66385da97cc8059196f8305c184a3e21440af -addnode=5.9.102.210 &
./komodod -pubkey=$pubkey -ac_name=KSB -ac_supply=1000000000 -ac_end=1 -ac_public=1 -addnode=37.187.225.231 &
./komodod -pubkey=$pubkey -ac_name=OUR -ac_reward=1478310502 -ac_halving=525600 -ac_cc=42 -ac_supply=100000000 -ac_perc=77700 -ac_staked=93 -ac_pubkey=02652a3f3e00b3a1875a918314f0bac838d6dd189a346fa623f5efe9541ac0b98c -ac_public=1 -addnode=51.255.195.65 -addnode=217.182.129.38 -addnode=37.187.225.231 &
./komodod -pubkey=$pubkey -ac_name=ILN -ac_supply=10000000000 -ac_cc=2 -addressindex=1 -spentindex=1 -addnode=51.75.122.83 &

View File

@@ -19,9 +19,16 @@
#include "CCinclude.h"
#define PAYMENTS_TXFEE 10000
bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
// CCcustom
UniValue PaymentsInfo();
UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr);
UniValue PaymentsFund(struct CCcontract_info *cp,char *jsonstr);
UniValue PaymentsTxidopret(struct CCcontract_info *cp,char *jsonstr);
UniValue PaymentsCreate(struct CCcontract_info *cp,char *jsonstr);
UniValue PaymentsInfo(struct CCcontract_info *cp,char *jsonstr);
UniValue PaymentsList(struct CCcontract_info *cp,char *jsonstr);
#endif

View File

@@ -29,7 +29,7 @@
bool AssetsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn);
// CCassetsCore
CScript EncodeAssetOpRet(uint8_t assetFuncId, uint256 assetid2, int64_t price, std::vector<uint8_t> origpubkey);
vscript_t EncodeAssetOpRet(uint8_t assetFuncId, uint256 assetid2, int64_t price, std::vector<uint8_t> origpubkey);
uint8_t DecodeAssetTokenOpRet(const CScript &scriptPubKey, uint8_t &assetsEvalCode, uint256 &tokenid, uint256 &assetid2, int64_t &price, std::vector<uint8_t> &origpubkey);
bool SetAssetOrigpubkey(std::vector<uint8_t> &origpubkey,int64_t &price,const CTransaction &tx);
int64_t IsAssetvout(struct CCcontract_info *cp, int64_t &price, std::vector<uint8_t> &origpubkey, const CTransaction& tx, int32_t v, uint256 refassetid);

View File

@@ -239,30 +239,30 @@ CScript EncodeAssetCreateOpRet(uint8_t funcid,std::vector<uint8_t> origpubkey,st
}
*/
CScript EncodeAssetOpRet(uint8_t assetFuncId, uint256 assetid2, int64_t price, std::vector<uint8_t> origpubkey)
vscript_t EncodeAssetOpRet(uint8_t assetFuncId, uint256 assetid2, int64_t price, std::vector<uint8_t> origpubkey)
{
CScript opret;
vscript_t vopret;
uint8_t evalcode = EVAL_ASSETS;
switch ( assetFuncId )
{
//case 't': this cannot be here
case 'x': case 'o':
opret << OP_RETURN << E_MARSHAL(ss << evalcode << assetFuncId);
vopret = /*<< OP_RETURN <<*/ E_MARSHAL(ss << evalcode << assetFuncId);
break;
case 's': case 'b': case 'S': case 'B':
opret << OP_RETURN << E_MARSHAL(ss << evalcode << assetFuncId << price << origpubkey);
vopret = /*<< OP_RETURN <<*/ E_MARSHAL(ss << evalcode << assetFuncId << price << origpubkey);
break;
case 'E': case 'e':
assetid2 = revuint256(assetid2);
opret << OP_RETURN << E_MARSHAL(ss << evalcode << assetFuncId << assetid2 << price << origpubkey);
vopret = /*<< OP_RETURN <<*/ E_MARSHAL(ss << evalcode << assetFuncId << assetid2 << price << origpubkey);
break;
default:
fprintf(stderr,"EncodeAssetOpRet: illegal funcid.%02x\n", assetFuncId);
opret << OP_RETURN;
//opret << OP_RETURN;
break;
}
return(opret);
return(vopret);
}
/* it is for compatibility, do not use this for new contracts (use DecodeTokenCreateOpRet)
@@ -281,10 +281,11 @@ bool DecodeAssetCreateOpRet(const CScript &scriptPubKey, std::vector<uint8_t> &o
uint8_t DecodeAssetTokenOpRet(const CScript &scriptPubKey, uint8_t &assetsEvalCode, uint256 &tokenid, uint256 &assetid2, int64_t &price, std::vector<uint8_t> &origpubkey)
{
std::vector<uint8_t> vopretAssets; //, vopretAssetsStripped;
vscript_t vopretAssets; //, vopretAssetsStripped;
uint8_t *script, funcId = 0, assetsFuncId = 0, dummyEvalCode, dummyAssetFuncId;
uint256 dummyTokenid;
std::vector<CPubKey> voutPubkeysDummy;
std::vector<std::pair<uint8_t, vscript_t>> oprets;
tokenid = zeroid;
assetid2 = zeroid;
@@ -293,7 +294,9 @@ uint8_t DecodeAssetTokenOpRet(const CScript &scriptPubKey, uint8_t &assetsEvalCo
assetsFuncId = 0;
// First - decode token opret:
funcId = DecodeTokenOpRet(scriptPubKey, dummyEvalCode, tokenid, voutPubkeysDummy, vopretAssets);
funcId = DecodeTokenOpRet(scriptPubKey, dummyEvalCode, tokenid, voutPubkeysDummy, oprets);
GetOpretBlob(oprets, OPRETID_ASSETSDATA, vopretAssets);
LOGSTREAM((char *)"ccassets", CCLOG_DEBUG2, stream << "DecodeAssetTokenOpRet() from DecodeTokenOpRet returned funcId=" << (int)funcId << std::endl);
if (funcId == 0 || vopretAssets.size() < 2) {

View File

@@ -353,9 +353,9 @@ std::string CreateBuyOffer(int64_t txfee, int64_t bidamount, uint256 assetid, in
mtx.vout.push_back(MakeCC1vout(EVAL_ASSETS, txfee, mypk));
std::vector<CPubKey> voutTokenPubkeys; // should be empty - no token vouts
return(FinalizeCCTx(0, cpAssets, mtx, mypk, txfee,
return FinalizeCCTx(0, cpAssets, mtx, mypk, txfee,
EncodeTokenOpRet(assetid, voutTokenPubkeys, // TODO: actually this tx is not 'tokens', maybe it is better not to have token opret here but only asset opret.
EncodeAssetOpRet('b', zeroid, pricetotal, Mypubkey())))); // But still such token opret should not make problems because no token eval in these vouts
std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet('b', zeroid, pricetotal, Mypubkey())))); // But still such token opret should not make problems because no token eval in these vouts
}
CCerror = strprintf("no coins found to make buy offer");
return("");
@@ -419,7 +419,7 @@ std::string CreateSell(int64_t txfee,int64_t askamount,uint256 assetid,int64_t p
return FinalizeCCTx(mask, cpTokens, mtx, mypk, txfee,
EncodeTokenOpRet(assetid, voutTokenPubkeys,
EncodeAssetOpRet('s', zeroid, pricetotal, Mypubkey())));
std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet('s', zeroid, pricetotal, Mypubkey()))));
}
else {
fprintf(stderr, "need some tokens to place ask\n");
@@ -540,7 +540,7 @@ std::string CancelBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid)
return(FinalizeCCTx(mask, cpAssets, mtx, mypk, txfee,
EncodeTokenOpRet(assetid, voutTokenPubkeys,
EncodeAssetOpRet('o', zeroid, 0, Mypubkey()))));
std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet('o', zeroid, 0, Mypubkey())))));
}
}
return("");
@@ -608,7 +608,7 @@ std::string CancelSell(int64_t txfee,uint256 assetid,uint256 asktxid)
return(FinalizeCCTx(mask, cpAssets, mtx, mypk, txfee,
EncodeTokenOpRet(assetid, voutTokenPubkeys,
EncodeAssetOpRet('x', zeroid, 0, Mypubkey()))));
std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet('x', zeroid, 0, Mypubkey())))));
}
}
return("");
@@ -695,7 +695,7 @@ std::string FillBuyOffer(int64_t txfee,uint256 assetid,uint256 bidtxid,int64_t f
return(FinalizeCCTx(mask, cpTokens, mtx, mypk, txfee,
EncodeTokenOpRet(assetid, voutTokenPubkeys,
EncodeAssetOpRet('B', zeroid, remaining_required, origpubkey))));
std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet('B', zeroid, remaining_required, origpubkey)))));
} else return("dont have any assets to fill bid");
}
}
@@ -820,7 +820,7 @@ std::string FillSell(int64_t txfee, uint256 assetid, uint256 assetid2, uint256 a
return(FinalizeCCTx(mask, cpAssets, mtx, mypk, txfee,
EncodeTokenOpRet(assetid, voutTokenPubkeys,
EncodeAssetOpRet(assetid2 != zeroid ? 'E' : 'S', assetid2, remaining_nValue, origpubkey))));
std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet(assetid2 != zeroid ? 'E' : 'S', assetid2, remaining_nValue, origpubkey)))));
} else {
CCerror = strprintf("filltx not enough utxos");
fprintf(stderr,"%s\n", CCerror.c_str());

View File

@@ -67,12 +67,29 @@ one other technical note is that komodod has the insight-explorer extensions bui
#include "../komodo_cJSON.h"
// opret data block ids:
enum {
OPRETID_NONFUNGIBLEDATA = 0x11
// TODO: OPRETID_ASSETSDATA = 0x12
// token opret additional data block ids:
enum opretid : uint8_t {
// cc contracts data:
OPRETID_NONFUNGIBLEDATA = 0x11,
OPRETID_ASSETSDATA = 0x12,
OPRETID_GATEWAYSDATA = 0x13,
OPRETID_CHANNELSDATA = 0x14,
OPRETID_HEIRDATA = 0x15,
OPRETID_ROGUEGAMEDATA = 0x16,
// non cc contract data:
OPRETID_FIRSTNONCCDATA = 0x80,
OPRETID_BURNDATA = 0x80,
OPRETID_IMPORTDATA = 0x81
};
// find opret blob by opretid
inline bool GetOpretBlob(const std::vector<std::pair<uint8_t, std::vector<uint8_t>>> &oprets, uint8_t id, std::vector<uint8_t> &vopret) {
vopret.clear();
for(auto p : oprets) if (p.first == id) { vopret = p.second; return true; }
return false;
}
struct CC_utxo
{
uint256 txid;
@@ -129,6 +146,8 @@ struct oracleprice_info
int32_t height;
};
typedef std::vector<uint8_t> vscript_t;
#ifdef ENABLE_WALLET
extern CWallet* pwalletMain;
#endif
@@ -151,7 +170,7 @@ static int32_t ignorevin;
bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock);
int32_t is_hexstr(char *str,int32_t n);
bool myAddtomempool(CTransaction &tx, CValidationState *pstate = NULL, bool fSkipExpiry = false);
int32_t CCgettxout(uint256 txid,int32_t vout,int32_t mempoolflag);
int32_t CCgettxout(uint256 txid,int32_t vout,int32_t mempoolflag,int32_t lockflag);
bool myIsutxo_spentinmempool(uint256 &spenttxid,int32_t &spentvini,uint256 txid,int32_t vout);
bool mytxid_inmempool(uint256 txid);
int32_t myIsutxo_spent(uint256 &spenttxid,uint256 txid,int32_t vout);
@@ -172,18 +191,23 @@ uint256 OraclesBatontxid(uint256 oracletxid,CPubKey pk);
//int64_t AddAssetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint256 assetid,int64_t total,int32_t maxinputs);
int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 tokenid, int64_t total, int32_t maxinputs);
int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 tokenid, int64_t total, int32_t maxinputs, std::vector<uint8_t> &vopretNonfungible);
int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 tokenid, int64_t total, int32_t maxinputs, vscript_t &vopretNonfungible);
int64_t IsTokensvout(bool goDeeper, bool checkPubkeys, struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, int32_t v, uint256 reftokenid);
bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx);
CScript EncodeTokenCreateOpRet(uint8_t funcid, std::vector<uint8_t> origpubkey, std::string name, std::string description, std::vector<uint8_t> vopretNonfungible);
CScript EncodeTokenOpRet(uint8_t tokenFuncId, uint8_t evalCodeInOpret, uint256 tokenid, std::vector<CPubKey> voutPubkeys, CScript payload); //old version
CScript EncodeTokenOpRet(uint256 tokenid, std::vector<CPubKey> voutPubkeys, CScript payload);
CScript EncodeTokenCreateOpRet(uint8_t funcid, std::vector<uint8_t> origpubkey, std::string name, std::string description, vscript_t vopretNonfungible);
CScript EncodeTokenCreateOpRet(uint8_t funcid, std::vector<uint8_t> origpubkey, std::string name, std::string description, std::vector<std::pair<uint8_t, vscript_t>> oprets);
CScript EncodeTokenImportOpRet(std::vector<uint8_t> origpubkey, std::string name, std::string description, uint256 srctokenid, std::vector<std::pair<uint8_t, vscript_t>> oprets);
CScript EncodeTokenOpRet(uint256 tokenid, std::vector<CPubKey> voutPubkeys, std::pair<uint8_t, vscript_t> opretWithId);
CScript EncodeTokenOpRet(uint256 tokenid, std::vector<CPubKey> voutPubkeys, std::vector<std::pair<uint8_t, vscript_t>> oprets);
int64_t AddCClibtxfee(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk);
uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey, std::vector<uint8_t> &origpubkey, std::string &name, std::string &description);
uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey, std::vector<uint8_t> &origpubkey, std::string &name, std::string &description, std::vector<uint8_t> &vopretNonfungible);
uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCodeTokens, uint256 &tokenid, std::vector<CPubKey> &voutPubkeys, std::vector<uint8_t> &vopretExtra);
void GetNonfungibleData(uint256 tokenid, std::vector<uint8_t> &vopretNonfungible);
uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey, std::vector<uint8_t> &origpubkey, std::string &name, std::string &description, std::vector<std::pair<uint8_t, vscript_t>> &oprets);
uint8_t DecodeTokenImportOpRet(const CScript &scriptPubKey, std::vector<uint8_t> &origpubkey, std::string &name, std::string &description, uint256 &srctokenid, std::vector<std::pair<uint8_t, vscript_t>> &oprets);
uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCodeTokens, uint256 &tokenid, std::vector<CPubKey> &voutPubkeys, std::vector<std::pair<uint8_t, vscript_t>> &oprets);
void GetNonfungibleData(uint256 tokenid, vscript_t &vopretNonfungible);
bool ExtractTokensCCVinPubkeys(const CTransaction &tx, std::vector<CPubKey> &vinPubkeys);
uint8_t DecodeOraclesData(const CScript &scriptPubKey,uint256 &oracletxid,uint256 &batontxid,CPubKey &pk,std::vector <uint8_t>&data);
int32_t oracle_format(uint256 *hashp,int64_t *valp,char *str,uint8_t fmt,uint8_t *data,int32_t offset,int32_t datalen);
@@ -227,7 +251,7 @@ uint256 revuint256(uint256 txid);
bool pubkey2addr(char *destaddr,uint8_t *pubkey33);
char *uint256_str(char *dest,uint256 txid);
char *pubkey33_str(char *dest,uint8_t *pubkey33);
uint256 Parseuint256(char *hexstr);
uint256 Parseuint256(const char *hexstr);
CPubKey pubkey2pk(std::vector<uint8_t> pubkey);
int64_t CCfullsupply(uint256 tokenid);
int64_t CCtoken_balance(char *destaddr,uint256 tokenid);

View File

@@ -34,197 +34,13 @@
Yes, this is quite confusing...
In ValudateTokenRemainder the naming convention is nValue is the coin/token with the offer on the books and "units" is what it is being paid in. The high level check is to make sure we didnt lose any coins or tokens, the harder to validate is the actual price paid as the "orderbook" is in terms of the combined nValue for the combined totalunits.
In ValidateTokenRemainder the naming convention is nValue is the coin/token with the offer on the books and "units" is what it is being paid in. The high level check is to make sure we didnt lose any coins or tokens, the harder to validate is the actual price paid as the "orderbook" is in terms of the combined nValue for the combined totalunits.
We assume that the effective unit cost in the orderbook is valid and that that amount was paid and also that any remainder will be close enough in effective unit cost to not matter. At the edge cases, this will probably be not true and maybe some orders wont be practically fillable when reduced to fractional state. However, the original pubkey that created the offer can always reclaim it.
------------------------------
*/
// NOTE: this inital tx won't be used by other contract
// for tokens to be used there should be at least one 't' tx with other contract's custom opret
CScript EncodeTokenCreateOpRet(uint8_t funcid, std::vector<uint8_t> origpubkey, std::string name, std::string description, std::vector<uint8_t> vopretNonfungible )
{
CScript opret;
uint8_t evalcode = EVAL_TOKENS;
funcid = 'c'; // override the param
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << origpubkey << name << description; \
if (!vopretNonfungible.empty()) { \
ss << (uint8_t)OPRETID_NONFUNGIBLEDATA; \
ss << vopretNonfungible; \
});
return(opret);
}
CScript EncodeTokenOpRet(uint256 tokenid, std::vector<CPubKey> voutPubkeys, CScript payload)
{
CScript opret;
uint8_t tokenFuncId = 't';
uint8_t evalCodeInOpret = EVAL_TOKENS;
tokenid = revuint256(tokenid);
uint8_t ccType = 0;
if (voutPubkeys.size() >= 0 && voutPubkeys.size() <= 2)
ccType = voutPubkeys.size();
else {
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG2, stream << "EncodeTokenOpRet voutPubkeys.size()=" << voutPubkeys.size() << " not supported" << std::endl);
}
std::vector<uint8_t> vpayload;
GetOpReturnData(payload, vpayload);
opret << OP_RETURN << E_MARSHAL(ss << evalCodeInOpret << tokenFuncId << tokenid << ccType; \
if (ccType >= 1) ss << voutPubkeys[0]; \
if (ccType == 2) ss << voutPubkeys[1]; \
if (vpayload.size() > 0) ss << vpayload);
// bad opret cases (retries to attach payload without re-serialization):
// "error 64: scriptpubkey":
// if (payload.size() > 0)
// opret += payload;
// error 64: scriptpubkey:
// CScript opretPayloadNoOpcode(vpayload);
// return opret + opretPayloadNoOpcode;
// error sig_aborted:
// opret.resize(opret.size() + vpayload.size());
// CScript::iterator it = opret.begin() + opret.size();
// for (int i = 0; i < vpayload.size(); i++, it++)
// *it = vpayload[i];
return opret;
}
// overload for compatibility
CScript EncodeTokenOpRet(uint8_t tokenFuncId, uint8_t evalCodeInOpret, uint256 tokenid, std::vector<CPubKey> voutPubkeys, CScript payload)
{
return EncodeTokenOpRet(tokenid, voutPubkeys, payload);
}
// overload for fungible:
uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey, std::vector<uint8_t> &origpubkey, std::string &name, std::string &description) {
std::vector<uint8_t> vopretNonfungibleDummy;
return DecodeTokenCreateOpRet(scriptPubKey, origpubkey, name, description, vopretNonfungibleDummy);
}
uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey,std::vector<uint8_t> &origpubkey,std::string &name,std::string &description, std::vector<uint8_t> &vopretNonfungible)
{
std::vector<uint8_t> vopret; uint8_t dummyEvalcode, funcid, *script, fieldId = 0;
GetOpReturnData(scriptPubKey, vopret);
script = (uint8_t *)vopret.data();
if ( script != 0 && vopret.size() > 2 && script[0] == EVAL_TOKENS && script[1] == 'c' )
{
if (E_UNMARSHAL(vopret, ss >> dummyEvalcode; ss >> funcid; ss >> origpubkey; ss >> name; ss >> description; \
// we suppose in 'c' opret it might be only non-fungible payload and not any assets/heir/etc payloads
if (!ss.eof()) { \
ss >> fieldId; \
if( fieldId == OPRETID_NONFUNGIBLEDATA ) \
ss >> vopretNonfungible; \
}))
return(funcid);
}
return (uint8_t)0;
}
// overload for compatibility allows only usual fungible tokens:
// warning: it makes vopret marshalling to CScript because this is what caller would expect
/*uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCode, uint256 &tokenid, std::vector<CPubKey> &voutPubkeys, std::vector<uint8_t> &vopretExtra) {
std::vector<uint8_t> vopret1, vopret2;
uint8_t funcId = DecodeTokenOpRet(scriptPubKey, evalCode, tokenid, voutPubkeys, vopret1, vopret2);
CScript opretExtra;
vopretExtra.clear();
// make marshalling for compatibility
// callers of this func expect length of full array at the beginning (and they will make 'vopretStripped' from vopretExtra)
if (vopret2.empty())
opretExtra << OP_RETURN << E_MARSHAL(ss << vopret1); // if first opret (or no oprets)
else
opretExtra << OP_RETURN << E_MARSHAL(ss << vopret2); // if both oprets present, return assets/heir/gateways/... opret (dump non-fungible opret)
GetOpReturnData(opretExtra, vopretExtra);
return funcId;
} */
// decodes token opret:
// for 't' returns all data from opret, vopretExtra contains other contract's data (currently only assets').
// for 'c' returns only funcid. NOTE: nonfungible data is not returned
uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCodeTokens, uint256 &tokenid, std::vector<CPubKey> &voutPubkeys, std::vector<uint8_t> &vopretExtra)
{
std::vector<uint8_t> vopret, extra, dummyPubkey, vnonfungibleDummy;
uint8_t funcId=0, *script, dummyEvalCode, dummyFuncId, ccType, fieldId = 0;
std::string dummyName; std::string dummyDescription;
CPubKey voutPubkey1, voutPubkey2;
GetOpReturnData(scriptPubKey, vopret);
script = (uint8_t *)vopret.data();
tokenid = zeroid;
vopretExtra.clear();
if (script != NULL && vopret.size() > 2)
{
// NOTE: if parse error occures, parse might not be able to set error. It is safer to treat that it was eof if it is not set!
bool isEof = true;
evalCodeTokens = script[0];
if (evalCodeTokens != EVAL_TOKENS)
return (uint8_t)0;
funcId = script[1];
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG2, stream << "DecodeTokenOpRet decoded funcId=" << (char)(funcId?funcId:' ') << std::endl);
switch( funcId )
{
case 'c':
return DecodeTokenCreateOpRet(scriptPubKey, dummyPubkey, dummyName, dummyDescription, vnonfungibleDummy);
//break;
case 't':
//not used yet: case 'l':
// NOTE: 'E_UNMARSHAL result==false' means 'parse error' OR 'not eof state'. Consequently, 'result==false' but 'isEof==true' means just 'parse error'
if (E_UNMARSHAL(vopret, ss >> dummyEvalCode; ss >> dummyFuncId; ss >> tokenid; ss >> ccType; \
if (ccType >= 1) ss >> voutPubkey1; \
if (ccType == 2) ss >> voutPubkey2; \
isEof = ss.eof(); \
if (!isEof) ss >> vopretExtra; \
// if something else remains -> bad format
isEof = ss.eof()) || !isEof)
{
if (!(ccType >= 0 && ccType <= 2)) { //incorrect ccType
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenOpRet() incorrect ccType=" << (int)ccType << " tokenid=" << revuint256(tokenid).GetHex() << std::endl);
return (uint8_t)0;
}
// add verification pubkeys:
voutPubkeys.clear();
if (voutPubkey1.IsValid())
voutPubkeys.push_back(voutPubkey1);
if (voutPubkey2.IsValid())
voutPubkeys.push_back(voutPubkey2);
tokenid = revuint256(tokenid);
return(funcId);
}
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenOpRet() bad opret format, isEof=" << isEof << " ccType=" << ccType << " tokenid=" << revuint256(tokenid).GetHex() << std::endl);
return (uint8_t)0;
default:
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenOpRet() illegal funcid=" << (int)funcId << std::endl);
return (uint8_t)0;
}
}
else {
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenOpRet() empty opret, could not parse" << std::endl);
}
return (uint8_t)0;
}
// tx validation
bool TokensValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &tx, uint32_t nIn)
@@ -233,7 +49,8 @@ bool TokensValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &
CTxDestination address; CTransaction vinTx, createTx; uint256 hashBlock, tokenid, tokenid2;
int32_t i, starti, numvins, numvouts, preventCCvins, preventCCvouts;
int64_t remaining_price, nValue, tokenoshis, outputs, inputs, tmpprice, totalunits, ignore;
std::vector<uint8_t> vopretExtra, tmporigpubkey, ignorepubkey;
std::vector<std::pair<uint8_t, vscript_t>> oprets;
vscript_t /*vopretExtra,*/ tmporigpubkey, ignorepubkey;
uint8_t funcid, evalCodeInOpret;
char destaddr[64], origaddr[64], CCaddr[64];
std::vector<CPubKey> voutTokenPubkeys, vinTokenPubkeys;
@@ -250,7 +67,7 @@ bool TokensValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &
if (numvouts < 1)
return eval->Invalid("no vouts");
if ((funcid = DecodeTokenOpRet(tx.vout[numvouts - 1].scriptPubKey, evalCodeInOpret, tokenid, voutTokenPubkeys, vopretExtra)) == 0)
if ((funcid = DecodeTokenOpRet(tx.vout[numvouts - 1].scriptPubKey, evalCodeInOpret, tokenid, voutTokenPubkeys, oprets)) == 0)
return eval->Invalid("TokenValidate: invalid opreturn payload");
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "TokensValidate funcId=" << (char)(funcid?funcid:' ') << " evalcode=" << std::hex << (int)cp->evalcode << std::endl);
@@ -272,11 +89,11 @@ bool TokensValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &
}
// validate spending from token cc addr: allowed only for burned non-fungible tokens:
if (ExtractTokensVinPubkeys(tx, vinTokenPubkeys) && std::find(vinTokenPubkeys.begin(), vinTokenPubkeys.end(), GetUnspendable(cp, NULL)) != vinTokenPubkeys.end()) {
if (ExtractTokensCCVinPubkeys(tx, vinTokenPubkeys) && std::find(vinTokenPubkeys.begin(), vinTokenPubkeys.end(), GetUnspendable(cp, NULL)) != vinTokenPubkeys.end()) {
// validate spending from token unspendable cc addr:
int64_t burnedAmount = HasBurnedTokensvouts(cp, eval, tx, tokenid);
if (burnedAmount > 0) {
std::vector<uint8_t> vopretNonfungible;
vscript_t vopretNonfungible;
GetNonfungibleData(tokenid, vopretNonfungible);
if( vopretNonfungible.empty() )
return eval->Invalid("spending cc marker not supported for fungible tokens");
@@ -331,13 +148,14 @@ bool TokensValidate(struct CCcontract_info *cp, Eval* eval, const CTransaction &
// helper funcs:
// extract cc token vins' pubkeys:
bool ExtractTokensVinPubkeys(CTransaction tx, std::vector<CPubKey> &vinPubkeys) {
bool ExtractTokensCCVinPubkeys(const CTransaction &tx, std::vector<CPubKey> &vinPubkeys) {
bool found = false;
CPubKey pubkey;
struct CCcontract_info *cpTokens, tokensC;
cpTokens = CCinit(&tokensC, EVAL_TOKENS);
vinPubkeys.clear();
for (int32_t i = 0; i < tx.vin.size(); i++)
{
@@ -384,7 +202,7 @@ uint8_t ValidateTokenOpret(CTransaction tx, uint256 tokenid) {
uint8_t funcid;
uint8_t dummyEvalCode;
std::vector<CPubKey> voutPubkeysDummy;
std::vector<uint8_t> vopretExtraDummy;
std::vector<std::pair<uint8_t, vscript_t>> opretsDummy;
// this is just for log messages indentation fur debugging recursive calls:
std::string indentStr = std::string().append(tokenValIndentSize, '.');
@@ -392,7 +210,7 @@ uint8_t ValidateTokenOpret(CTransaction tx, uint256 tokenid) {
if (tx.vout.size() == 0)
return (uint8_t)0;
if ((funcid = DecodeTokenOpRet(tx.vout.back().scriptPubKey, dummyEvalCode, tokenidOpret, voutPubkeysDummy, vopretExtraDummy)) == 0)
if ((funcid = DecodeTokenOpRet(tx.vout.back().scriptPubKey, dummyEvalCode, tokenidOpret, voutPubkeysDummy, opretsDummy)) == 0)
{
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << indentStr << "ValidateTokenOpret() DecodeTokenOpret could not parse opret for txid=" << tx.GetHash().GetHex() << std::endl);
return (uint8_t)0;
@@ -400,13 +218,23 @@ uint8_t ValidateTokenOpret(CTransaction tx, uint256 tokenid) {
else if (funcid == 'c')
{
if (tokenid != zeroid && tokenid == tx.GetHash()) {
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << indentStr << "ValidateTokenOpret() this is the tokenbase 'c' tx, txid=" << tx.GetHash().GetHex() << " returning true" << std::endl);
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << indentStr << "ValidateTokenOpret() this is tokenbase 'c' tx, txid=" << tx.GetHash().GetHex() << " returning true" << std::endl);
return funcid;
}
else {
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << indentStr << "ValidateTokenOpret() not my tokenbase txid=" << tx.GetHash().GetHex() << std::endl);
}
}
else if (funcid == 'i')
{
if (tokenid != zeroid && tokenid == tx.GetHash()) {
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << indentStr << "ValidateTokenOpret() this is import 'i' tx, txid=" << tx.GetHash().GetHex() << " returning true" << std::endl);
return funcid;
}
else {
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << indentStr << "ValidateTokenOpret() not my import txid=" << tx.GetHash().GetHex() << std::endl);
}
}
else if (funcid == 't')
{
//std::cerr << indentStr << "ValidateTokenOpret() tokenid=" << tokenid.GetHex() << " tokenIdOpret=" << tokenidOpret.GetHex() << " txid=" << tx.GetHash().GetHex() << std::endl;
@@ -425,17 +253,31 @@ uint8_t ValidateTokenOpret(CTransaction tx, uint256 tokenid) {
}
// remove token->unspendablePk (it is only for marker usage)
std::vector<CPubKey> FilterOutTokensUnspendablePk(std::vector<CPubKey> sourcePubkeys) {
void FilterOutTokensUnspendablePk(const std::vector<CPubKey> &sourcePubkeys, std::vector<CPubKey> &destPubkeys) {
struct CCcontract_info *cpTokens, tokensC;
cpTokens = CCinit(&tokensC, EVAL_TOKENS);
CPubKey tokensUnspendablePk = GetUnspendable(cpTokens, NULL);
std::vector<CPubKey> destPubkeys;
destPubkeys.clear();
for (auto pk : sourcePubkeys)
if (pk != tokensUnspendablePk)
destPubkeys.push_back(pk);
return destPubkeys;
}
void FilterOutNonCCOprets(const std::vector<std::pair<uint8_t, vscript_t>> &oprets, vscript_t &vopret) {
vopret.clear();
if (oprets.size() > 2)
LOGSTREAM("cctokens", CCLOG_INFO, stream << "FilterOutNonCCOprets() warning!! oprets.size > 2 currently not supported" << oprets.size() << std::endl);
for (auto o : oprets) {
if (o.first < OPRETID_FIRSTNONCCDATA) { // skip burn, import, etc opret data
vopret = o.second; // return first contract opret (more than 1 is not supported yet)
break;
}
}
}
// Checks if the vout is a really Tokens CC vout
@@ -488,7 +330,8 @@ int64_t IsTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true
uint8_t dummyEvalCode;
uint256 tokenIdOpret;
std::vector<CPubKey> voutPubkeys, voutPubkeysInOpret;
std::vector<uint8_t> vopretExtra, vopretNonfungible;
vscript_t vopretExtra, vopretNonfungible;
std::vector<std::pair<uint8_t, vscript_t>> oprets;
uint8_t evalCode = EVAL_TOKENS; // if both payloads are empty maybe it is a transfer to non-payload-one-eval-token vout like GatewaysClaim
uint8_t evalCode2 = 0; // will be checked if zero or not
@@ -496,12 +339,16 @@ int64_t IsTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true
// test vouts for possible token use-cases:
std::vector<std::pair<CTxOut, std::string>> testVouts;
DecodeTokenOpRet(tx.vout.back().scriptPubKey, dummyEvalCode, tokenIdOpret, voutPubkeysInOpret, vopretExtra);
DecodeTokenOpRet(tx.vout.back().scriptPubKey, dummyEvalCode, tokenIdOpret, voutPubkeysInOpret, oprets);
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG2, stream << "IsTokensvout() oprets.size()=" << oprets.size() << std::endl);
// get assets/channels/gateways token data:
FilterOutNonCCOprets(oprets, vopretExtra); // NOTE: only 1 additional evalcode in token opret is currently supported
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG2, stream << "IsTokensvout() vopretExtra=" << HexStr(vopretExtra) << std::endl);
// get non-fungible data
GetNonfungibleData(reftokenid, vopretNonfungible);
voutPubkeys = FilterOutTokensUnspendablePk(voutPubkeysInOpret); // cannot send tokens to token unspendable cc addr (only marker is allowed there)
FilterOutTokensUnspendablePk(voutPubkeysInOpret, voutPubkeys); // cannot send tokens to token unspendable cc addr (only marker is allowed there)
// NOTE: evalcode order in vouts is important:
// non-fungible-eval -> EVAL_TOKENS -> assets-eval
@@ -512,7 +359,7 @@ int64_t IsTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true
evalCode2 = vopretExtra.begin()[0];
if (evalCode == EVAL_TOKENS && evalCode2 != 0) {
evalCode = evalCode2;
evalCode = evalCode2; // for using MakeTokensCC1vout(evalcode,...) instead of MakeCC1vout(EVAL_TOKENS, evalcode...)
evalCode2 = 0;
}
@@ -562,8 +409,8 @@ int64_t IsTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true
// maybe it is single-eval or dual/three-eval token change?
std::vector<CPubKey> vinPubkeys, vinPubkeysUnfiltered;
ExtractTokensVinPubkeys(tx, vinPubkeysUnfiltered);
vinPubkeys = FilterOutTokensUnspendablePk(vinPubkeysUnfiltered); // cannot send tokens to token unspendable cc addr (only marker is allowed there)
ExtractTokensCCVinPubkeys(tx, vinPubkeysUnfiltered);
FilterOutTokensUnspendablePk(vinPubkeysUnfiltered, vinPubkeys); // cannot send tokens to token unspendable cc addr (only marker is allowed there)
for(std::vector<CPubKey>::iterator it = vinPubkeys.begin(); it != vinPubkeys.end(); it++) {
testVouts.push_back(std::make_pair(MakeCC1vout(EVAL_TOKENS, tx.vout[v].nValue, *it), std::string("single-eval cc1 self vin pk")));
@@ -577,11 +424,11 @@ int64_t IsTokensvout(bool goDeeper, bool checkPubkeys /*<--not used, always true
}
else {
CPubKey origPubkey;
std::vector<uint8_t> vorigPubkey;
vscript_t vorigPubkey;
std::string dummyName, dummyDescription;
std::vector<uint8_t> vopret1;
std::vector<std::pair<uint8_t, vscript_t>> oprets;
if (DecodeTokenCreateOpRet(tx.vout.back().scriptPubKey, vorigPubkey, dummyName, dummyDescription, vopret1) == 0) {
if (DecodeTokenCreateOpRet(tx.vout.back().scriptPubKey, vorigPubkey, dummyName, dummyDescription, oprets) == 0) {
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << indentStr << "IsTokensvout() could not decode create opret" << " for txid=" << tx.GetHash().GetHex() << " for tokenid=" << reftokenid.GetHex() << std::endl);
return 0;
}
@@ -689,7 +536,7 @@ bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cp, int64_t &inpu
// get non-fungible data from 'tokenbase' tx (the data might be empty)
void GetNonfungibleData(uint256 tokenid, std::vector<uint8_t> &vopretNonfungible)
void GetNonfungibleData(uint256 tokenid, vscript_t &vopretNonfungible)
{
CTransaction tokenbasetx;
uint256 hashBlock;
@@ -704,22 +551,24 @@ void GetNonfungibleData(uint256 tokenid, std::vector<uint8_t> &vopretNonfungible
if (tokenbasetx.vout.size() > 0) {
std::vector<uint8_t> origpubkey;
std::string name, description;
std::vector<uint8_t> vopretExtra;
if (DecodeTokenCreateOpRet(tokenbasetx.vout.back().scriptPubKey, origpubkey, name, description, vopretExtra) == 'c')
vopretNonfungible = vopretExtra;
std::vector<std::pair<uint8_t, vscript_t>> oprets;
if (DecodeTokenCreateOpRet(tokenbasetx.vout.back().scriptPubKey, origpubkey, name, description, oprets) == 'c') {
GetOpretBlob(oprets, OPRETID_NONFUNGIBLEDATA, vopretNonfungible);
}
}
}
// overload, adds inputs from token cc addr
int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 tokenid, int64_t total, int32_t maxinputs) {
std::vector<uint8_t> vopretNonfungibleDummy;
vscript_t vopretNonfungibleDummy;
return AddTokenCCInputs(cp, mtx, pk, tokenid, total, maxinputs, vopretNonfungibleDummy);
}
// adds inputs from token cc addr and returns non-fungible opret payload if present
// also sets evalcode in cp, if needed
int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 tokenid, int64_t total, int32_t maxinputs, std::vector<uint8_t> &vopretNonfungible)
int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, CPubKey pk, uint256 tokenid, int64_t total, int32_t maxinputs, vscript_t &vopretNonfungible)
{
char tokenaddr[64], destaddr[64];
int64_t threshold, nValue, price, totalinputs = 0;
@@ -737,8 +586,7 @@ int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, C
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "AddTokenCCInputs() no utxos for token dual/three eval addr=" << tokenaddr << " evalcode=" << (int)cp->evalcode << " additionalTokensEvalcode2=" << (int)cp->additionalTokensEvalcode2 << std::endl);
}
threshold = total / (maxinputs != 0 ? maxinputs : 64); // TODO: maxinputs really could not be over 64? what if i want to calc total balance for all available uxtos?
// maybe it is better to add all uxtos if maxinputs == 0
threshold = total / (maxinputs != 0 ? maxinputs : CC_MAXVINS);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it = unspentOutputs.begin(); it != unspentOutputs.end(); it++)
{
@@ -771,7 +619,7 @@ int64_t AddTokenCCInputs(struct CCcontract_info *cp, CMutableTransaction &mtx, C
{
//for non-fungible tokens check payload:
if (!vopretNonfungible.empty()) {
std::vector<uint8_t> vopret;
vscript_t vopret;
// check if it is non-fungible token:
GetNonfungibleData(tokenid, vopret);
@@ -807,7 +655,8 @@ int64_t HasBurnedTokensvouts(struct CCcontract_info *cp, Eval* eval, const CTran
uint8_t dummyEvalCode;
uint256 tokenIdOpret;
std::vector<CPubKey> voutPubkeys, voutPubkeysDummy;
std::vector<uint8_t> vopretExtra, vopretNonfungible;
std::vector<std::pair<uint8_t, vscript_t>> oprets;
vscript_t vopretExtra, vopretNonfungible;
uint8_t evalCode = EVAL_TOKENS; // if both payloads are empty maybe it is a transfer to non-payload-one-eval-token vout like GatewaysClaim
uint8_t evalCode2 = 0; // will be checked if zero or not
@@ -823,11 +672,14 @@ int64_t HasBurnedTokensvouts(struct CCcontract_info *cp, Eval* eval, const CTran
}
if (DecodeTokenOpRet(tx.vout.back().scriptPubKey, dummyEvalCode, tokenIdOpret, voutPubkeysDummy, vopretExtra) == 0) {
if (DecodeTokenOpRet(tx.vout.back().scriptPubKey, dummyEvalCode, tokenIdOpret, voutPubkeysDummy, oprets) == 0) {
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "HasBurnedTokensvouts() cannot parse opret DecodeTokenOpRet returned 0, txid=" << tx.GetHash().GetHex() << std::endl);
return 0;
}
// get assets/channels/gateways token data:
FilterOutNonCCOprets(oprets, vopretExtra); // NOTE: only 1 additional evalcode in token opret is currently supported
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG2, stream << "HasBurnedTokensvouts() vopretExtra=" << HexStr(vopretExtra) << std::endl);
GetNonfungibleData(reftokenid, vopretNonfungible);
@@ -874,18 +726,40 @@ int64_t HasBurnedTokensvouts(struct CCcontract_info *cp, Eval* eval, const CTran
return burnedAmount;
}
std::string CreateToken(int64_t txfee, int64_t tokensupply, std::string name, std::string description, std::vector<uint8_t> nonfungibleData)
CPubKey GetTokenOriginatorPubKey(CScript scriptPubKey) {
uint8_t funcId, evalCode;
uint256 tokenid;
std::vector<CPubKey> voutTokenPubkeys;
std::vector<std::pair<uint8_t, vscript_t>> oprets;
if ((funcId = DecodeTokenOpRet(scriptPubKey, evalCode, tokenid, voutTokenPubkeys, oprets)) != 0) {
CTransaction tokenbasetx;
uint256 hashBlock;
if (myGetTransaction(tokenid, tokenbasetx, hashBlock) && tokenbasetx.vout.size() > 0) {
vscript_t vorigpubkey;
std::string name, desc;
if (DecodeTokenCreateOpRet(tokenbasetx.vout.back().scriptPubKey, vorigpubkey, name, desc) != 0)
return pubkey2pk(vorigpubkey);
}
}
return CPubKey(); //return invalid pubkey
}
std::string CreateToken(int64_t txfee, int64_t tokensupply, std::string name, std::string description, vscript_t nonfungibleData)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk; struct CCcontract_info *cp, C;
if (tokensupply < 0)
{
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "CreateToken() negative tokensupply=" << tokensupply << std::endl);
if (tokensupply < 0) {
CCerror = "negative tokensupply";
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "CreateToken() =" << CCerror << "=" << tokensupply << std::endl);
return std::string("");
}
if (!nonfungibleData.empty() && tokensupply != 1) {
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "CreateToken() for non-fungible tokens tokensupply should be equal to 1" << std::endl);
CCerror = "for non-fungible tokens tokensupply should be equal to 1";
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "CreateToken() " << CCerror << std::endl);
return std::string("");
}
@@ -893,8 +767,8 @@ std::string CreateToken(int64_t txfee, int64_t tokensupply, std::string name, st
cp = CCinit(&C, EVAL_TOKENS);
if (name.size() > 32 || description.size() > 4096) // this is also checked on rpc level
{
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "name of=" << name.size() << " or description of=" << description.size() << " is too big" << std::endl);
CCerror = "name should be < 32, description should be < 4096";
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "name len=" << name.size() << " or description len=" << description.size() << " is too big" << std::endl);
CCerror = "name should be <= 32, description should be <= 4096";
return("");
}
if (txfee == 0)
@@ -916,21 +790,22 @@ std::string CreateToken(int64_t txfee, int64_t tokensupply, std::string name, st
return(FinalizeCCTx(0, cp, mtx, mypk, txfee, EncodeTokenCreateOpRet('c', Mypubkey(), name, description, nonfungibleData)));
}
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "cant find normal inputs" << std::endl);
CCerror = "cant find normal inputs";
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "CreateToken() " << CCerror << std::endl);
return std::string("");
}
// transfer tokens to another pubkey
// param additionalEvalCode allows transfer of dual-eval non-fungible tokens
std::string TokenTransfer(int64_t txfee, uint256 tokenid, std::vector<uint8_t> destpubkey, int64_t total)
std::string TokenTransfer(int64_t txfee, uint256 tokenid, vscript_t destpubkey, int64_t total)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk; uint64_t mask; int64_t CCchange = 0, inputs = 0; struct CCcontract_info *cp, C;
std::vector<uint8_t> vopretNonfungible;
vscript_t vopretNonfungible, vopretEmpty;
if (total < 0) {
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "negative total=" << total << std::endl);
CCerror = strprintf("negative total");
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << CCerror << "=" << total << std::endl);
return("");
}
@@ -946,8 +821,8 @@ std::string TokenTransfer(int64_t txfee, uint256 tokenid, std::vector<uint8_t> d
if ((inputs = AddTokenCCInputs(cp, mtx, mypk, tokenid, total, 60, vopretNonfungible)) > 0) // NOTE: AddTokenCCInputs might set cp->additionalEvalCode which is used in FinalizeCCtx!
{
if (inputs < total) { //added dimxy
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "TokenTransfer(): insufficient token funds" << std::endl);
CCerror = strprintf("insufficient token inputs");
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "TokenTransfer() " << CCerror << std::endl);
return std::string("");
}
@@ -964,17 +839,17 @@ std::string TokenTransfer(int64_t txfee, uint256 tokenid, std::vector<uint8_t> d
std::vector<CPubKey> voutTokenPubkeys;
voutTokenPubkeys.push_back(pubkey2pk(destpubkey)); // dest pubkey for validating vout
return(FinalizeCCTx(mask, cp, mtx, mypk, txfee, EncodeTokenOpRet(tokenid, voutTokenPubkeys, CScript())));
return FinalizeCCTx(mask, cp, mtx, mypk, txfee, EncodeTokenOpRet(tokenid, voutTokenPubkeys, std::make_pair((uint8_t)0, vopretEmpty)));
}
else {
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "not enough CC token inputs for amount=" << total << std::endl);
CCerror = strprintf("no token inputs");
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "TokenTransfer() " << CCerror << total << std::endl);
}
//} else fprintf(stderr,"numoutputs.%d != numamounts.%d\n",n,(int32_t)amounts.size());
}
else {
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "not enough normal inputs for txfee" << std::endl);
CCerror = strprintf("insufficient normal inputs");
CCerror = strprintf("insufficient normal inputs for tx fee");
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "TokenTransfer() " << CCerror << std::endl);
}
return("");
}
@@ -1007,7 +882,8 @@ UniValue TokenInfo(uint256 tokenid)
uint256 hashBlock;
CTransaction vintx;
std::vector<uint8_t> origpubkey;
std::vector<uint8_t> vopretNonfungible;
std::vector<std::pair<uint8_t, vscript_t>> oprets;
vscript_t vopretNonfungible;
std::string name, description;
struct CCcontract_info *cpTokens, tokensCCinfo;
@@ -1020,7 +896,7 @@ UniValue TokenInfo(uint256 tokenid)
result.push_back(Pair("error", "cant find tokenid"));
return(result);
}
if (vintx.vout.size() > 0 && DecodeTokenCreateOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, origpubkey, name, description, vopretNonfungible) == 0)
if (vintx.vout.size() > 0 && DecodeTokenCreateOpRet(vintx.vout[vintx.vout.size() - 1].scriptPubKey, origpubkey, name, description, oprets) != 'c')
{
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "TokenInfo() passed tokenid isnt token creation txid" << std::endl);
result.push_back(Pair("result", "error"));
@@ -1038,6 +914,8 @@ UniValue TokenInfo(uint256 tokenid)
supply += output;
result.push_back(Pair("supply", supply));
result.push_back(Pair("description", description));
GetOpretBlob(oprets, OPRETID_NONFUNGIBLEDATA, vopretNonfungible);
if( !vopretNonfungible.empty() )
result.push_back(Pair("data", HexStr(vopretNonfungible)));

View File

@@ -30,8 +30,8 @@ bool TokensValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx
bool TokensExactAmounts(bool goDeeper, struct CCcontract_info *cpTokens, int64_t &inputs, int64_t &outputs, Eval* eval, const CTransaction &tx, uint256 tokenid);
std::string CreateToken(int64_t txfee, int64_t assetsupply, std::string name, std::string description, std::vector<uint8_t> nonfungibleData);
std::string TokenTransfer(int64_t txfee, uint256 assetid, std::vector<uint8_t> destpubkey, int64_t total);
bool ExtractTokensVinPubkeys(CTransaction tx, std::vector<CPubKey> &vinPubkeys);
int64_t HasBurnedTokensvouts(struct CCcontract_info *cp, Eval* eval, const CTransaction& tx, uint256 reftokenid);
CPubKey GetTokenOriginatorPubKey(CScript scriptPubKey);
int64_t GetTokenBalance(CPubKey pk, uint256 tokenid);
UniValue TokenInfo(uint256 tokenid);

296
src/cc/CCtokensOpRet.cpp Normal file
View File

@@ -0,0 +1,296 @@
// encode decode tokens opret
// (moved to a separate file to enable linking lib common.so with importcoin.cpp)
#include "CCtokens.h"
#ifndef IS_CHARINSTR
#define IS_CHARINSTR(c, str) (std::string(str).find((char)(c)) != std::string::npos)
#endif
// NOTE: this inital tx won't be used by other contract
// for tokens to be used there should be at least one 't' tx with other contract's custom opret
CScript EncodeTokenCreateOpRet(uint8_t funcid, std::vector<uint8_t> origpubkey, std::string name, std::string description, vscript_t vopretNonfungible)
{
/* CScript opret;
uint8_t evalcode = EVAL_TOKENS;
funcid = 'c'; // override the param
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << origpubkey << name << description; \
if (!vopretNonfungible.empty()) {
ss << (uint8_t)OPRETID_NONFUNGIBLEDATA;
ss << vopretNonfungible;
}); */
std::vector<std::pair<uint8_t, vscript_t>> oprets;
if(!vopretNonfungible.empty())
oprets.push_back(std::make_pair(OPRETID_NONFUNGIBLEDATA, vopretNonfungible));
return EncodeTokenCreateOpRet(funcid, origpubkey, name, description, oprets);
}
CScript EncodeTokenCreateOpRet(uint8_t funcid, std::vector<uint8_t> origpubkey, std::string name, std::string description, std::vector<std::pair<uint8_t, vscript_t>> oprets)
{
CScript opret;
uint8_t evalcode = EVAL_TOKENS;
funcid = 'c'; // override the param
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << origpubkey << name << description;
for (auto o : oprets) {
if (o.first != 0) {
ss << (uint8_t)o.first;
ss << o.second;
}
});
return(opret);
}
// opret 'i' for imported tokens
CScript EncodeTokenImportOpRet(std::vector<uint8_t> origpubkey, std::string name, std::string description, uint256 srctokenid, std::vector<std::pair<uint8_t, vscript_t>> oprets)
{
CScript opret;
uint8_t evalcode = EVAL_TOKENS;
uint8_t funcid = 'i';
srctokenid = revuint256(srctokenid); // do not forget this
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << origpubkey << name << description << srctokenid;
for (auto o : oprets) {
if (o.first != 0) {
ss << (uint8_t)o.first;
ss << o.second;
}
});
return(opret);
}
CScript EncodeTokenOpRet(uint256 tokenid, std::vector<CPubKey> voutPubkeys, std::pair<uint8_t, vscript_t> opretWithId)
{
std::vector<std::pair<uint8_t, vscript_t>> oprets;
oprets.push_back(opretWithId);
return EncodeTokenOpRet(tokenid, voutPubkeys, oprets);
}
CScript EncodeTokenOpRet(uint256 tokenid, std::vector<CPubKey> voutPubkeys, std::vector<std::pair<uint8_t, vscript_t>> oprets)
{
CScript opret;
uint8_t tokenFuncId = 't';
uint8_t evalCodeInOpret = EVAL_TOKENS;
tokenid = revuint256(tokenid);
uint8_t ccType = 0;
if (voutPubkeys.size() >= 0 && voutPubkeys.size() <= 2)
ccType = voutPubkeys.size();
else {
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG2, stream << "EncodeTokenOpRet voutPubkeys.size()=" << voutPubkeys.size() << " not supported" << std::endl);
}
//vopret_t vpayload;
//GetOpReturnData(payload, vpayload);
opret << OP_RETURN << E_MARSHAL(ss << evalCodeInOpret << tokenFuncId << tokenid << ccType;
if (ccType >= 1) ss << voutPubkeys[0];
if (ccType == 2) ss << voutPubkeys[1];
for (auto o : oprets) {
if (o.first != 0) {
ss << (uint8_t)o.first;
ss << o.second;
}
});
// bad opret cases (tries to attach payload without re-serialization):
// error "64: scriptpubkey":
// if (payload.size() > 0)
// opret += payload;
// error "64: scriptpubkey":
// CScript opretPayloadNoOpcode(vpayload);
// return opret + opretPayloadNoOpcode;
// error "sig_aborted":
// opret.resize(opret.size() + vpayload.size());
// CScript::iterator it = opret.begin() + opret.size();
// for (int i = 0; i < vpayload.size(); i++, it++)
// *it = vpayload[i];
return opret;
}
// overload for compatibility
//CScript EncodeTokenOpRet(uint8_t tokenFuncId, uint8_t evalCodeInOpret, uint256 tokenid, std::vector<CPubKey> voutPubkeys, CScript payload)
//{
// return EncodeTokenOpRet(tokenid, voutPubkeys, payload);
//}
// overload for fungible tokens (no additional data in opret):
uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey, std::vector<uint8_t> &origpubkey, std::string &name, std::string &description) {
//vopret_t vopretNonfungibleDummy;
std::vector<std::pair<uint8_t, vscript_t>> opretsDummy;
return DecodeTokenCreateOpRet(scriptPubKey, origpubkey, name, description, opretsDummy);
}
uint8_t DecodeTokenCreateOpRet(const CScript &scriptPubKey, std::vector<uint8_t> &origpubkey, std::string &name, std::string &description, std::vector<std::pair<uint8_t, vscript_t>> &oprets)
{
vscript_t vopret, vblob;
uint8_t dummyEvalcode, funcid, opretId = 0;
GetOpReturnData(scriptPubKey, vopret);
oprets.clear();
if (vopret.size() > 2 && vopret.begin()[0] == EVAL_TOKENS && vopret.begin()[1] == 'c')
{
if (E_UNMARSHAL(vopret, ss >> dummyEvalcode; ss >> funcid; ss >> origpubkey; ss >> name; ss >> description;
while (!ss.eof()) {
ss >> opretId;
if (!ss.eof()) {
ss >> vblob;
oprets.push_back(std::make_pair(opretId, vblob));
}
}))
{
return(funcid);
}
}
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenCreateOpRet() incorrect token create opret" << std::endl);
return (uint8_t)0;
}
// for imported tokens
uint8_t DecodeTokenImportOpRet(const CScript &scriptPubKey, std::vector<uint8_t> &origpubkey, std::string &name, std::string &description, uint256 &srctokenid, std::vector<std::pair<uint8_t, vscript_t>> &oprets)
{
vscript_t vopret, vblob;
uint8_t dummyEvalcode, funcid, opretId = 0;
GetOpReturnData(scriptPubKey, vopret);
oprets.clear();
if (vopret.size() > 2 && vopret.begin()[0] == EVAL_TOKENS && vopret.begin()[1] == 'i')
{
if (E_UNMARSHAL(vopret, ss >> dummyEvalcode; ss >> funcid; ss >> origpubkey; ss >> name; ss >> description; ss >> srctokenid;
while (!ss.eof()) {
ss >> opretId;
if (!ss.eof()) {
ss >> vblob;
oprets.push_back(std::make_pair(opretId, vblob));
}
}))
{
srctokenid = revuint256(srctokenid); // do not forget this
return(funcid);
}
}
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenImportOpRet() incorrect token import opret" << std::endl);
return (uint8_t)0;
}
// decodes token opret:
// for 't' returns all data from opret, vopretExtra contains other contract's data (currently only assets').
// for 'c' and 'i' returns only funcid. NOTE: nonfungible data is not returned
uint8_t DecodeTokenOpRet(const CScript scriptPubKey, uint8_t &evalCodeTokens, uint256 &tokenid, std::vector<CPubKey> &voutPubkeys, std::vector<std::pair<uint8_t, vscript_t>> &oprets)
{
vscript_t vopret, vblob, dummyPubkey, vnonfungibleDummy;
uint8_t funcId = 0, *script, dummyEvalCode, dummyFuncId, ccType, opretId = 0;
std::string dummyName; std::string dummyDescription;
uint256 dummySrcTokenId;
CPubKey voutPubkey1, voutPubkey2;
vscript_t voldstyledata;
bool foundOldstyle = false;
GetOpReturnData(scriptPubKey, vopret);
script = (uint8_t *)vopret.data();
tokenid = zeroid;
oprets.clear();
if (script != NULL && vopret.size() > 2)
{
// NOTE: if parse error occures, parse might not be able to set error. It is safer to treat that it was eof if it is not set!
// bool isEof = true;
evalCodeTokens = script[0];
if (evalCodeTokens != EVAL_TOKENS) {
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenOpRet() incorrect evalcode in tokens opret" << std::endl);
return (uint8_t)0;
}
funcId = script[1];
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG2, stream << "DecodeTokenOpRet decoded funcId=" << (char)(funcId ? funcId : ' ') << std::endl);
switch (funcId)
{
case 'c':
return DecodeTokenCreateOpRet(scriptPubKey, dummyPubkey, dummyName, dummyDescription, oprets);
case 'i':
return DecodeTokenImportOpRet(scriptPubKey, dummyPubkey, dummyName, dummyDescription, dummySrcTokenId, oprets);
//break;
case 't':
// compatibility with old-style rogue or assets data (with no opretid):
// try to unmarshal old-style rogue or assets data:
foundOldstyle = E_UNMARSHAL(vopret, ss >> dummyEvalCode; ss >> dummyFuncId; ss >> tokenid; ss >> ccType;
if (ccType >= 1) ss >> voutPubkey1;
if (ccType == 2) ss >> voutPubkey2;
if (!ss.eof()) {
ss >> voldstyledata;
}) && voldstyledata.size() >= 2 &&
(voldstyledata.begin()[0] == 0x11 /*EVAL_ROGUE*/ && IS_CHARINSTR(voldstyledata.begin()[1], "RHQKG") ||
voldstyledata.begin()[0] == EVAL_ASSETS && IS_CHARINSTR(voldstyledata.begin()[1], "sbSBxo")) ;
if (foundOldstyle || // fix for compatibility with old style data (no opretid)
E_UNMARSHAL(vopret, ss >> dummyEvalCode; ss >> dummyFuncId; ss >> tokenid; ss >> ccType;
if (ccType >= 1) ss >> voutPubkey1;
if (ccType == 2) ss >> voutPubkey2;
while (!ss.eof()) {
ss >> opretId;
if (!ss.eof()) {
ss >> vblob;
oprets.push_back(std::make_pair(opretId, vblob));
}
}))
{
if (!(ccType >= 0 && ccType <= 2)) { //incorrect ccType
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenOpRet() incorrect ccType=" << (int)ccType << " tokenid=" << revuint256(tokenid).GetHex() << std::endl);
return (uint8_t)0;
}
// add verification pubkeys:
voutPubkeys.clear();
if (voutPubkey1.IsValid())
voutPubkeys.push_back(voutPubkey1);
if (voutPubkey2.IsValid())
voutPubkeys.push_back(voutPubkey2);
tokenid = revuint256(tokenid);
if (foundOldstyle) { //patch for old-style opret data with no opretid
LOGSTREAM((char *)"cctokens", CCLOG_DEBUG1, stream << "DecodeTokenOpRet() found old-style rogue/asset data, evalcode=" << (int)voldstyledata.begin()[0] << " funcid=" << (char)voldstyledata.begin()[1] << " for tokenid=" << revuint256(tokenid).GetHex() << std::endl);
uint8_t opretIdRestored;
if (voldstyledata.begin()[0] == 0x11 /*EVAL_ROGUE*/)
opretIdRestored = OPRETID_ROGUEGAMEDATA;
else // EVAL_ASSETS
opretIdRestored = OPRETID_ASSETSDATA;
oprets.push_back(std::make_pair(opretIdRestored, voldstyledata));
}
return(funcId);
}
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenOpRet() bad opret format," << " ccType=" << (int)ccType << " tokenid=" << revuint256(tokenid).GetHex() << std::endl);
return (uint8_t)0;
default:
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenOpRet() illegal funcid=" << (int)funcId << std::endl);
return (uint8_t)0;
}
}
else {
LOGSTREAM((char *)"cctokens", CCLOG_INFO, stream << "DecodeTokenOpRet() empty opret, could not parse" << std::endl);
}
return (uint8_t)0;
}

View File

@@ -290,6 +290,16 @@ std::string FinalizeCCTx(uint64_t CCmask,struct CCcontract_info *cp,CMutableTran
cc_free(othercond3);
if ( othercond4 != 0 )
cc_free(othercond4);
if ( othercond1of2 != 0 )
cc_free(othercond1of2);
if ( othercond1of2tokens != 0 )
cc_free(othercond1of2tokens);
if ( mytokenscond != 0 )
cc_free(mytokenscond);
if ( mysingletokenscond != 0 )
cc_free(mysingletokenscond);
if ( othertokenscond != 0 )
cc_free(othertokenscond);
std::string strHex = EncodeHexTx(mtx);
if ( strHex.size() > 0 )
return(strHex);
@@ -347,17 +357,29 @@ int64_t CCutxovalue(char *coinaddr,uint256 utxotxid,int32_t utxovout)
return(0);
}
int32_t CCgettxout(uint256 txid,int32_t vout,int32_t mempoolflag)
int32_t CCgettxout(uint256 txid,int32_t vout,int32_t mempoolflag,int32_t lockflag)
{
CCoins coins;
//fprintf(stderr,"CCgettxoud %s/v%d\n",txid.GetHex().c_str(),vout);
if ( mempoolflag != 0 )
{
LOCK(mempool.cs);
CCoinsViewMemPool view(pcoinsTip, mempool);
if (!view.GetCoins(txid, coins))
return(-1);
if ( myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) != 0 )
return(-1);
if ( lockflag != 0 )
{
LOCK(mempool.cs);
CCoinsViewMemPool view(pcoinsTip, mempool);
if (!view.GetCoins(txid, coins))
return(-1);
else if ( myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) != 0 )
return(-1);
}
else
{
CCoinsViewMemPool view(pcoinsTip, mempool);
if (!view.GetCoins(txid, coins))
return(-1);
else if ( myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) != 0 )
return(-1);
}
}
else
{
@@ -399,7 +421,7 @@ int64_t CCfullsupply(uint256 tokenid)
{
if (DecodeTokenCreateOpRet(tx.vout[numvouts-1].scriptPubKey,origpubkey,name,description))
{
return(tx.vout[0].nValue);
return(tx.vout[1].nValue);
}
}
return(0);
@@ -420,7 +442,8 @@ int64_t CCtoken_balance(char *coinaddr,uint256 reftokenid)
{
char str[65];
std::vector<CPubKey> voutTokenPubkeys;
if ( reftokenid==txid || (DecodeTokenOpRet(tx.vout[numvouts-1].scriptPubKey, evalCode, tokenid, voutTokenPubkeys, vopretExtra) != 0 && reftokenid == tokenid))
std::vector<std::pair<uint8_t, vscript_t>> oprets;
if ( reftokenid==txid || (DecodeTokenOpRet(tx.vout[numvouts-1].scriptPubKey, evalCode, tokenid, voutTokenPubkeys, oprets) != 0 && reftokenid == tokenid))
{
sum += it->second.satoshis;
}
@@ -486,16 +509,18 @@ int32_t CC_vinselect(int32_t *aboveip,int64_t *abovep,int32_t *belowip,int64_t *
int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int32_t maxinputs)
{
int32_t abovei,belowi,ind,vout,i,n = 0,maxutxos=CC_MAXVINS; int64_t sum,threshold,above,below; int64_t remains,nValue,totalinputs = 0; uint256 txid,hashBlock; std::vector<COutput> vecOutputs; CTransaction tx; struct CC_utxo *utxos,*up;
int32_t abovei,belowi,ind,vout,i,n = 0; int64_t sum,threshold,above,below; int64_t remains,nValue,totalinputs = 0; uint256 txid,hashBlock; std::vector<COutput> vecOutputs; CTransaction tx; struct CC_utxo *utxos,*up;
#ifdef ENABLE_WALLET
assert(pwalletMain != NULL);
const CKeyStore& keystore = *pwalletMain;
LOCK2(cs_main, pwalletMain->cs_wallet);
pwalletMain->AvailableCoins(vecOutputs, false, NULL, true);
utxos = (struct CC_utxo *)calloc(maxutxos,sizeof(*utxos));
threshold = total/(maxinputs+1);
if ( maxinputs > maxutxos )
maxutxos = maxinputs;
utxos = (struct CC_utxo *)calloc(CC_MAXVINS,sizeof(*utxos));
if ( maxinputs > CC_MAXVINS )
maxinputs = CC_MAXVINS;
if ( maxinputs > 0 )
threshold = total/maxinputs;
else threshold = total;
sum = 0;
BOOST_FOREACH(const COutput& out, vecOutputs)
{
@@ -530,7 +555,7 @@ int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int3
up->vout = vout;
sum += up->nValue;
//fprintf(stderr,"add %.8f to vins array.%d of %d\n",(double)up->nValue/COIN,n,maxutxos);
if ( n >= maxutxos || sum >= total )
if ( n >= maxinputs || sum >= total )
break;
}
}
@@ -579,12 +604,14 @@ int64_t AddNormalinputs(CMutableTransaction &mtx,CPubKey mypk,int64_t total,int3
int64_t AddNormalinputs2(CMutableTransaction &mtx,int64_t total,int32_t maxinputs)
{
int32_t abovei,belowi,ind,vout,i,n = 0,maxutxos=CC_MAXVINS; int64_t sum,threshold,above,below; int64_t remains,nValue,totalinputs = 0; char coinaddr[64]; uint256 txid,hashBlock; CTransaction tx; struct CC_utxo *utxos,*up;
int32_t abovei,belowi,ind,vout,i,n = 0; int64_t sum,threshold,above,below; int64_t remains,nValue,totalinputs = 0; char coinaddr[64]; uint256 txid,hashBlock; CTransaction tx; struct CC_utxo *utxos,*up;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
utxos = (struct CC_utxo *)calloc(maxutxos,sizeof(*utxos));
threshold = total/(maxinputs+1);
if ( maxinputs > maxutxos )
maxutxos = maxinputs;
utxos = (struct CC_utxo *)calloc(CC_MAXVINS,sizeof(*utxos));
if ( maxinputs > CC_MAXVINS )
maxinputs = CC_MAXVINS;
if ( maxinputs > 0 )
threshold = total/maxinputs;
else threshold = total;
sum = 0;
Getscriptaddress(coinaddr,CScript() << Mypubkey() << OP_CHECKSIG);
SetCCunspents(unspentOutputs,coinaddr);
@@ -621,7 +648,7 @@ int64_t AddNormalinputs2(CMutableTransaction &mtx,int64_t total,int32_t maxinput
up->vout = vout;
sum += up->nValue;
//fprintf(stderr,"add %.8f to vins array.%d of %d\n",(double)up->nValue/COIN,n,maxutxos);
if ( n >= maxutxos || sum >= total )
if ( n >= maxinputs || sum >= total )
break;
}
}

105
src/cc/CCutilbits.cpp Normal file
View File

@@ -0,0 +1,105 @@
/******************************************************************************
* Copyright © 2014-2019 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
/*
CCutilbits.cpp has very low level functions that are universally useful for all contracts and have low dependency from other sources
*/
#include "CCinclude.h"
#include "komodo_structs.h"
int32_t unstringbits(char *buf,uint64_t bits)
{
int32_t i;
for (i=0; i<8; i++,bits>>=8)
if ( (buf[i]= (char)(bits & 0xff)) == 0 )
break;
buf[i] = 0;
return(i);
}
uint64_t stringbits(char *str)
{
uint64_t bits = 0;
if ( str == 0 )
return(0);
int32_t i,n = (int32_t)strlen(str);
if ( n > 8 )
n = 8;
for (i=n-1; i>=0; i--)
bits = (bits << 8) | (str[i] & 0xff);
//printf("(%s) -> %llx %llu\n",str,(long long)bits,(long long)bits);
return(bits);
}
uint256 revuint256(uint256 txid)
{
uint256 revtxid; int32_t i;
for (i=31; i>=0; i--)
((uint8_t *)&revtxid)[31-i] = ((uint8_t *)&txid)[i];
return(revtxid);
}
char *uint256_str(char *dest,uint256 txid)
{
int32_t i,j=0;
for (i=31; i>=0; i--)
sprintf(&dest[j++ * 2],"%02x",((uint8_t *)&txid)[i]);
dest[64] = 0;
return(dest);
}
char *pubkey33_str(char *dest,uint8_t *pubkey33)
{
int32_t i;
if ( pubkey33 != 0 )
{
for (i=0; i<33; i++)
sprintf(&dest[i * 2],"%02x",pubkey33[i]);
} else dest[0] = 0;
return(dest);
}
uint256 Parseuint256(const char *hexstr)
{
uint256 txid; int32_t i; std::vector<unsigned char> txidbytes(ParseHex(hexstr));
memset(&txid,0,sizeof(txid));
if ( strlen(hexstr) == 64 )
{
for (i=31; i>=0; i--)
((uint8_t *)&txid)[31-i] = ((uint8_t *)txidbytes.data())[i];
}
return(txid);
}
CPubKey buf2pk(uint8_t *buf33)
{
CPubKey pk; int32_t i; uint8_t *dest;
dest = (uint8_t *)pk.begin();
for (i=0; i<33; i++)
dest[i] = buf33[i];
return(pk);
}
CPubKey pubkey2pk(std::vector<uint8_t> pubkey)
{
CPubKey pk; int32_t i,n; uint8_t *dest,*pubkey33;
n = pubkey.size();
dest = (uint8_t *)pk.begin();
pubkey33 = (uint8_t *)pubkey.data();
for (i=0; i<n; i++)
dest[i] = pubkey33[i];
return(pk);
}

View File

@@ -168,89 +168,6 @@ bool IsCCInput(CScript const& scriptSig)
return true;
}
int32_t unstringbits(char *buf,uint64_t bits)
{
int32_t i;
for (i=0; i<8; i++,bits>>=8)
if ( (buf[i]= (char)(bits & 0xff)) == 0 )
break;
buf[i] = 0;
return(i);
}
uint64_t stringbits(char *str)
{
uint64_t bits = 0;
if ( str == 0 )
return(0);
int32_t i,n = (int32_t)strlen(str);
if ( n > 8 )
n = 8;
for (i=n-1; i>=0; i--)
bits = (bits << 8) | (str[i] & 0xff);
//printf("(%s) -> %llx %llu\n",str,(long long)bits,(long long)bits);
return(bits);
}
uint256 revuint256(uint256 txid)
{
uint256 revtxid; int32_t i;
for (i=31; i>=0; i--)
((uint8_t *)&revtxid)[31-i] = ((uint8_t *)&txid)[i];
return(revtxid);
}
char *uint256_str(char *dest,uint256 txid)
{
int32_t i,j=0;
for (i=31; i>=0; i--)
sprintf(&dest[j++ * 2],"%02x",((uint8_t *)&txid)[i]);
dest[64] = 0;
return(dest);
}
char *pubkey33_str(char *dest,uint8_t *pubkey33)
{
int32_t i;
if ( pubkey33 != 0 )
{
for (i=0; i<33; i++)
sprintf(&dest[i * 2],"%02x",pubkey33[i]);
} else dest[0] = 0;
return(dest);
}
uint256 Parseuint256(char *hexstr)
{
uint256 txid; int32_t i; std::vector<unsigned char> txidbytes(ParseHex(hexstr));
memset(&txid,0,sizeof(txid));
if ( strlen(hexstr) == 64 )
{
for (i=31; i>=0; i--)
((uint8_t *)&txid)[31-i] = ((uint8_t *)txidbytes.data())[i];
}
return(txid);
}
CPubKey buf2pk(uint8_t *buf33)
{
CPubKey pk; int32_t i; uint8_t *dest;
dest = (uint8_t *)pk.begin();
for (i=0; i<33; i++)
dest[i] = buf33[i];
return(pk);
}
CPubKey pubkey2pk(std::vector<uint8_t> pubkey)
{
CPubKey pk; int32_t i,n; uint8_t *dest,*pubkey33;
n = pubkey.size();
dest = (uint8_t *)pk.begin();
pubkey33 = (uint8_t *)pubkey.data();
for (i=0; i<n; i++)
dest[i] = pubkey33[i];
return(pk);
}
// set additional 'unspendable' addr
void CCaddr2set(struct CCcontract_info *cp,uint8_t evalcode,CPubKey pk,uint8_t *priv,char *coinaddr)

View File

@@ -4,7 +4,7 @@ CC_DARWIN = g++-6
CC_WIN = x86_64-w64-mingw32-gcc-posix
CFLAGS_DARWIN = -DBUILD_ROGUE -std=c++11 -arch x86_64 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -Wl,-undefined -Wl,dynamic_lookup -Wno-write-strings -shared -dynamiclib
CFLAGS = -Wno-write-strings -DBUILD_ROGUE -std=c++11 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared
CFLAGS_WIN = -Wno-write-strings -DBUILD_ROGUE -std=c++11 -I../../depends/x86_64-w64-mingw32/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared
CFLAGS_WIN = -Wno-write-strings -DBUILD_ROGUE -std=c++11 -I./rogue/x86_64-w64-mingw32/include -I./rogue/x86_64-w64-mingw32/include/ncursesw -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared
DEBUGFLAGS = -O0 -D _DEBUG
RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program
$(info $(OS))

View File

@@ -146,6 +146,13 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti
numvouts = tx.vout.size();
outputsDummy = inputs = 0;
preventCCvins = preventCCvouts = -1;
// add specific chains exceptions for old token support:
if (strcmp(ASSETCHAINS_SYMBOL, "SEC") == 0 && chainActive.Height() <= 144073)
return true;
if (strcmp(ASSETCHAINS_SYMBOL, "MGNX") == 0 && chainActive.Height() <= 210190)
return true;
// add specific chains exceptions for old token support:
if (strcmp(ASSETCHAINS_SYMBOL, "SEC") == 0 && chainActive.Height() <= 144073)
@@ -290,6 +297,7 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti
return eval->Invalid("vout2 doesnt go to origpubkey fillbuy");
else if ( inputs != tx.vout[2].nValue + tx.vout[4].nValue )
return eval->Invalid("asset inputs doesnt match vout2+3 fillbuy");
preventCCvouts ++;
}
else if( ConstrainVout(tx.vout[2], 1, origTokensCCaddr, inputs) == 0 ) // tokens to originator cc addr (tokens+nonfungible evals)
return eval->Invalid("vout2 doesnt match inputs fillbuy");
@@ -461,7 +469,7 @@ bool AssetsValidate(struct CCcontract_info *cpAssets,Eval* eval,const CTransacti
}
// what does this do?
bool bPrevent = PreventCC(eval, tx, preventCCvins, numvins, preventCCvouts, numvouts);
bool bPrevent = PreventCC(eval, tx, preventCCvins, numvins, preventCCvouts, numvouts); // seems we do not need this call as we already checked vouts well
//std::cerr << "AssetsValidate() PreventCC returned=" << bPrevent << std::endl;
return (bPrevent);
}

View File

@@ -33,8 +33,12 @@
#ifdef BUILD_ROGUE
#define EVAL_ROGUE 17
std::string MYCCLIBNAME = (char *)"rogue";
#else
#elif BUILD_CUSTOMCC
#include "customcc.h"
#else
#define EVAL_SUDOKU 17
#define EVAL_MUSIG 18
#define EVAL_DILITHIUM 19
@@ -67,6 +71,8 @@ CClib_methods[] =
{ (char *)"rogue", (char *)"games", (char *)"<no args>", 0, 0, 'F', EVAL_ROGUE },
{ (char *)"rogue", (char *)"setname", (char *)"pname", 1, 1, 'N', EVAL_ROGUE },
{ (char *)"rogue", (char *)"extract", (char *)"gametxid [pubkey]", 1, 2, 'X', EVAL_ROGUE },
#elif BUILD_CUSTOMCC
RPC_FUNCS
#else
{ (char *)"sudoku", (char *)"gen", (char *)"<no args>", 0, 0, 'G', EVAL_SUDOKU },
{ (char *)"sudoku", (char *)"txidinfo", (char *)"txid", 1, 1, 'T', EVAL_SUDOKU },
@@ -83,10 +89,12 @@ CClib_methods[] =
{ (char *)"musig", (char *)"spend", (char *)"sendtxid sig scriptPubKey", 3, 3, 'y', EVAL_MUSIG },
{ (char *)"dilithium", (char *)"keypair", (char *)"[hexseed]", 0, 1, 'K', EVAL_DILITHIUM },
{ (char *)"dilithium", (char *)"register", (char *)"handle, [hexseed]", 1, 2, 'R', EVAL_DILITHIUM },
{ (char *)"dilithium", (char *)"handleinfo", (char *)"handle", 1, 1, 'I', EVAL_DILITHIUM },
{ (char *)"dilithium", (char *)"sign", (char *)"msg [hexseed]", 1, 2, 'S', EVAL_DILITHIUM },
{ (char *)"dilithium", (char *)"verify", (char *)"pubtxid msg sig", 3, 3, 'V', EVAL_DILITHIUM },
{ (char *)"dilithium", (char *)"send", (char *)"handle pubtxid amount", 3, 3, 'x', EVAL_DILITHIUM },
{ (char *)"dilithium", (char *)"spend", (char *)"sendtxid scriptPubKey [hexseed]", 2, 3, 'y', EVAL_DILITHIUM },
{ (char *)"dilithium", (char *)"Qsend", (char *)"mypubtxid hexseed/'mypriv' destpubtxid,amount, ...", 4, 66, 'Q', EVAL_DILITHIUM },
#endif
};
@@ -129,11 +137,13 @@ UniValue musig_spend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
bool dilithium_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx);
UniValue dilithium_register(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue dilithium_handleinfo(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue dilithium_send(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue dilithium_spend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue dilithium_keypair(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue dilithium_sign(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue dilithium_verify(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue dilithium_Qsend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
#endif
@@ -210,6 +220,8 @@ UniValue CClib_method(struct CCcontract_info *cp,char *method,char *jsonstr)
return(result);
}
}
#elif BUILD_CUSTOMCC
CUSTOM_DISPATCH
#else
if ( cp->evalcode == EVAL_SUDOKU )
{
@@ -261,7 +273,9 @@ UniValue CClib_method(struct CCcontract_info *cp,char *method,char *jsonstr)
}
else if ( cp->evalcode == EVAL_DILITHIUM )
{
if ( strcmp(method,"send") == 0 )
if ( strcmp(method,"Qsend") == 0 )
return(dilithium_Qsend(txfee,cp,params));
else if ( strcmp(method,"send") == 0 )
return(dilithium_send(txfee,cp,params));
else if ( strcmp(method,"spend") == 0 )
return(dilithium_spend(txfee,cp,params));
@@ -269,6 +283,8 @@ UniValue CClib_method(struct CCcontract_info *cp,char *method,char *jsonstr)
return(dilithium_keypair(txfee,cp,params));
else if ( strcmp(method,"register") == 0 )
return(dilithium_register(txfee,cp,params));
else if ( strcmp(method,"handleinfo") == 0 )
return(dilithium_handleinfo(txfee,cp,params));
else if ( strcmp(method,"sign") == 0 )
return(dilithium_sign(txfee,cp,params));
else if ( strcmp(method,"verify") == 0 )
@@ -402,6 +418,8 @@ bool CClib_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const C
{
#ifdef BUILD_ROGUE
return(rogue_validate(cp,height,eval,tx));
#elif BUILD_CUSTOMCC
return(custom_validate(cp,height,eval,tx));
#else
if ( cp->evalcode == EVAL_SUDOKU )
return(sudoku_validate(cp,height,eval,tx));
@@ -474,7 +492,11 @@ int64_t AddCClibInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubK
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
GetCCaddress(cp,coinaddr,pk);
SetCCunspents(unspentOutputs,coinaddr);
threshold = total/(maxinputs+1);
if ( maxinputs > CC_MAXVINS )
maxinputs = CC_MAXVINS;
if ( maxinputs != 0 )
threshold = total/maxinputs;
else threshold = total;
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
txid = it->first.txhash;
@@ -500,6 +522,31 @@ int64_t AddCClibInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubK
return(totalinputs);
}
int64_t AddCClibtxfee(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk)
{
char coinaddr[64]; int64_t nValue,txfee = 10000; uint256 txid,hashBlock; CTransaction vintx; int32_t vout;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
GetCCaddress(cp,coinaddr,pk);
SetCCunspents(unspentOutputs,coinaddr);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
txid = it->first.txhash;
vout = (int32_t)it->first.index;
//char str[65]; fprintf(stderr,"%s check %s/v%d %.8f vs %.8f\n",coinaddr,uint256_str(str,txid),vout,(double)it->second.satoshis/COIN,(double)threshold/COIN);
if ( it->second.satoshis < txfee )
continue;
if ( GetTransaction(txid,vintx,hashBlock,false) != 0 )
{
if ( (nValue= IsCClibvout(cp,vintx,vout,coinaddr)) != 0 && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 )
{
mtx.vin.push_back(CTxIn(txid,vout,CScript()));
return(it->second.satoshis);
} //else fprintf(stderr,"nValue %.8f too small or already spent in mempool\n",(double)nValue/COIN);
} else fprintf(stderr,"couldnt get tx\n");
}
return(0);
}
std::string Faucet2Fund(struct CCcontract_info *cp,uint64_t txfee,int64_t funds)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
@@ -627,6 +674,9 @@ int32_t cclib_parsehash(uint8_t *hash32,cJSON *item,int32_t len)
#include "rogue/weapons.c"
#include "rogue/wizard.c"
#elif BUILD_CUSTOMCC
#include "customcc.cpp"
#else
#include "sudoku.cpp"
#include "musig.cpp"

View File

@@ -92,24 +92,27 @@ int64_t IsChannelsMarkervout(struct CCcontract_info *cp,const CTransaction& tx,C
CScript EncodeChannelsOpRet(uint8_t funcid,uint256 tokenid,uint256 opentxid,CPubKey srcpub,CPubKey destpub,int32_t numpayments,int64_t payment,uint256 hashchain)
{
CScript opret; uint8_t evalcode = EVAL_CHANNELS;
vscript_t vopret;
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << opentxid << srcpub << destpub << numpayments << payment << hashchain);
vopret = E_MARSHAL(ss << evalcode << funcid << opentxid << srcpub << destpub << numpayments << payment << hashchain);
if (tokenid!=zeroid)
{
std::vector<CPubKey> pks;
pks.push_back(srcpub);
pks.push_back(destpub);
return(EncodeTokenOpRet(tokenid,pks,opret));
return(EncodeTokenOpRet(tokenid,pks, std::make_pair(OPRETID_CHANNELSDATA, vopret)));
}
opret << OP_RETURN << vopret;
return(opret);
}
uint8_t DecodeChannelsOpRet(const CScript &scriptPubKey, uint256 &tokenid, uint256 &opentxid, CPubKey &srcpub,CPubKey &destpub,int32_t &numpayments,int64_t &payment,uint256 &hashchain)
{
std::vector<std::pair<uint8_t, vscript_t>> oprets;
std::vector<uint8_t> vopret,vOpretExtra; uint8_t *script,e,f,tokenevalcode;
std::vector<CPubKey> pubkeys;
if (DecodeTokenOpRet(scriptPubKey,tokenevalcode,tokenid,pubkeys,vOpretExtra)!=0 && tokenevalcode==EVAL_TOKENS && vOpretExtra.size()>0)
if (DecodeTokenOpRet(scriptPubKey,tokenevalcode,tokenid,pubkeys,oprets)!=0 && GetOpretBlob(oprets, OPRETID_CHANNELSDATA, vOpretExtra) && tokenevalcode==EVAL_TOKENS && vOpretExtra.size()>0)
{
vopret=vOpretExtra;
}

88
src/cc/customcc.cpp Normal file
View File

@@ -0,0 +1,88 @@
/*
simple stub custom cc
Just update the functions in this file, then from ~/komodo/src/cc
../komodo-cli -ac_name=CUSTOM stop
./makecustom
../komodod -ac_name=CUSTOM -ac_cclib=custom -ac_cc=2 ...
The above will rebuild komodod and get it running again
*/
CScript custom_opret(uint8_t funcid,CPubKey pk)
{
CScript opret; uint8_t evalcode = EVAL_CUSTOM;
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << pk);
return(opret);
}
uint8_t custom_opretdecode(CPubKey &pk,CScript scriptPubKey)
{
std::vector<uint8_t> vopret; uint8_t e,f;
GetOpReturnData(scriptPubKey,vopret);
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> pk) != 0 && e == EVAL_CUSTOM )
{
return(f);
}
return(0);
}
UniValue custom_rawtxresult(UniValue &result,std::string rawtx,int32_t broadcastflag)
{
CTransaction tx;
if ( rawtx.size() > 0 )
{
result.push_back(Pair("hex",rawtx));
if ( DecodeHexTx(tx,rawtx) != 0 )
{
if ( broadcastflag != 0 && myAddtomempool(tx) != 0 )
RelayTransaction(tx);
result.push_back(Pair("txid",tx.GetHash().ToString()));
result.push_back(Pair("result","success"));
} else result.push_back(Pair("error","decode hex"));
} else result.push_back(Pair("error","couldnt finalize CCtx"));
return(result);
}
UniValue custom_func0(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
UniValue result(UniValue::VOBJ);
result.push_back(Pair("result","success"));
result.push_back(Pair("message","just an example of an information returning rpc"));
return(result);
}
// send yourself 1 coin to your CC address using normal utxo from your -pubkey
UniValue custom_func1(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); std::string rawtx;
UniValue result(UniValue::VOBJ); CPubKey mypk; int64_t amount = COIN; int32_t broadcastflag=0;
if ( txfee == 0 )
txfee = CUSTOM_TXFEE;
mypk = pubkey2pk(Mypubkey());
if ( AddNormalinputs(mtx,mypk,COIN+txfee,64) >= COIN+txfee ) // add utxo to mtx
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,mypk)); // make vout0
// add opreturn, change is automatically added and tx is properly signed
rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,custom_opret('1',mypk));
return(custom_rawtxresult(result,rawtx,broadcastflag));
}
return(result);
}
bool custom_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx)
{
char expectedaddress[64]; CPubKey pk;
if ( tx.vout.size() != 2 ) // make sure the tx only has 2 outputs
return eval->Invalid("invalid number of vouts");
else if ( custom_opretdecode(pk,tx.vout[1].scriptPubKey) != '1' ) // verify has opreturn
return eval->Invalid("invalid opreturn");
GetCCaddress(cp,expectedaddress,pk);
if ( IsCClibvout(cp,tx,0,expectedaddress) == COIN ) // make sure amount and destination matches
return(true);
else return eval->Invalid("invalid vout0 amount");
}

45
src/cc/customcc.h Normal file
View File

@@ -0,0 +1,45 @@
/*
to create a custom libcc.so:
1. change "func0" and "func1" to method names that fit your custom cc. Of course, you can create more functions by adding another entry to RPC_FUNCS. there is not any practical limit to the number of methods.
2. For each method make sure there is a UniValue function declaration and CUSTOM_DISPATCH has an if statement checking for it that calls the custom_func
3. write the actual custom_func0, custom_func1 and custom_validate in customcc.cpp
4. ./makecustom, which builds cclib.cpp with -DBUILD_CUSTOMCC and puts the libcc.so in ~/komodo/src and rebuilds komodod
5. launch your chain with -ac_cclib=customcc -ac_cc=2
*/
std::string MYCCLIBNAME = (char *)"customcc";
#define EVAL_CUSTOM (EVAL_FAUCET2+1)
#define CUSTOM_TXFEE 10000
#define MYCCNAME "custom"
#define RPC_FUNCS \
{ (char *)MYCCNAME, (char *)"func0", (char *)"<parameter help>", 1, 1, '0', EVAL_CUSTOM }, \
{ (char *)MYCCNAME, (char *)"func1", (char *)"<no args>", 0, 0, '1', EVAL_CUSTOM },
bool custom_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx);
UniValue custom_func0(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
UniValue custom_func1(uint64_t txfee,struct CCcontract_info *cp,cJSON *params);
#define CUSTOM_DISPATCH \
if ( cp->evalcode == EVAL_CUSTOM ) \
{ \
if ( strcmp(method,"func0") == 0 ) \
return(custom_func0(txfee,cp,params)); \
else if ( strcmp(method,"func1") == 0 ) \
return(custom_func1(txfee,cp,params)); \
else \
{ \
result.push_back(Pair("result","error")); \
result.push_back(Pair("error","invalid customcc method")); \
result.push_back(Pair("method",method)); \
return(result); \
} \
}

View File

@@ -1052,9 +1052,11 @@ uint64_t AddDiceInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubK
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
GetCCaddress(cp,coinaddr,pk);
SetCCunspents(unspentOutputs,coinaddr);
if ( maxinputs > CC_MAXVINS )
maxinputs = CC_MAXVINS;
if ( maxinputs > 0 )
threshold = total / maxinputs;
else threshold = total / 64;
else threshold = total;
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
txid = it->first.txhash;
@@ -1213,6 +1215,9 @@ int64_t DicePlanFunds(uint64_t &entropyval,uint256 &entropytxid,uint64_t refsbit
} else {
return(0);
}
//fprintf(stderr,"numentropy tx %d: %.8f\n",n,(double)totalinputs/COIN);
entropytxs = n;
return(totalinputs);
}
bool DicePlanExists(CScript &fundingPubKey,uint256 &fundingtxid,struct CCcontract_info *cp,uint64_t refsbits,CPubKey dicepk,int64_t &minbet,int64_t &maxbet,int64_t &maxodds,int64_t &timeoutblocks)

View File

@@ -2908,6 +2908,20 @@ int32_t main(void)
this generates a really big hex, broadcast it and if all went well it will get confirmed.
a dilithium spend!
to generate a seed that wont be directly derivable from an secp256k1 keypair, do:
cclib keypair 19 \"[%22rand%22]\"
to do a Qsend (multiple dilithium inputs and outputs)
cclib Qsend 19 \"[%22mypubtxid%22,%22<hexseed>%22,%22<destpubtxid>%22,0.777]\"
there can be up to 64 outputs, where each one can be a different destpubtxid or scriptPubKey. The only restriction is that scriptPubKey hex cant be 32 bytes.
Qsend is able to spend many Qvins as long as they are for the same dilithium bigpub + secp pub33. And the outputs can be to many different Qvouts or normal vouts. This allows to keep funds totally within the dilithium system and also to transfer back to normal taddrs. Qsend currently only sends from Qfunds, though it could also use funds from normal inputs.
Currently, to get funds from normal inputs to a dilithium, the send rpc can be used as above. So that provides a way to push funds into dilithium. The spend rpc becomes redundant with Qsend.
To properly test this, we need to make sure that transactions Qsend can use send outputs, and Qsend outputs and a combination. Of course, it needs to be validated that funds are not lost, Qsends work properly, etc.
*/
#define DILITHIUM_TXFEE 10000
@@ -2915,6 +2929,69 @@ int32_t main(void)
void calc_rmd160_sha256(uint8_t rmd160[20],uint8_t *data,int32_t datalen);
char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len);
struct dilithium_handle
{
UT_hash_handle hh;
uint256 destpubtxid;
char handle[32];
} *Dilithium_handles;
pthread_mutex_t DILITHIUM_MUTEX;
struct dilithium_handle *dilithium_handlenew(char *handle)
{
struct dilithium_handle *hashstr = 0; int32_t len = (int32_t)strlen(handle);
if ( len < sizeof(Dilithium_handles[0].handle)-1 )
{
pthread_mutex_lock(&DILITHIUM_MUTEX);
HASH_FIND(hh,Dilithium_handles,handle,len,hashstr);
if ( hashstr == 0 )
{
hashstr = (struct dilithium_handle *)calloc(1,sizeof(*hashstr));
strncpy(hashstr->handle,handle,sizeof(hashstr->handle));
HASH_ADD_KEYPTR(hh,Dilithium_handles,hashstr->handle,len,hashstr);
}
pthread_mutex_unlock(&DILITHIUM_MUTEX);
}
return(hashstr);
}
struct dilithium_handle *dilithium_handlefind(char *handle)
{
struct dilithium_handle *hashstr = 0; int32_t len = (int32_t)strlen(handle);
if ( len < sizeof(Dilithium_handles[0].handle)-1 )
{
pthread_mutex_lock(&DILITHIUM_MUTEX);
HASH_FIND(hh,Dilithium_handles,handle,len,hashstr);
pthread_mutex_unlock(&DILITHIUM_MUTEX);
}
return(hashstr);
}
int32_t dilithium_Qmsghash(uint8_t *msg,CTransaction tx,int32_t numvouts,std::vector<uint256> voutpubtxids)
{
CScript data; uint256 hash; int32_t i,numvins,len = 0; std::vector<uint256> vintxids; std::vector<int32_t> vinprevns; std::vector<CTxOut> vouts;
numvins = tx.vin.size();
for (i=0; i<numvins; i++)
{
vintxids.push_back(tx.vin[i].prevout.hash);
vinprevns.push_back(tx.vin[i].prevout.n);
//fprintf(stderr,"%s/v%d ",tx.vin[i].prevout.hash.GetHex().c_str(),tx.vin[i].prevout.n);
}
for (i=0; i<numvouts; i++)
{
//char destaddr[64];
//Getscriptaddress(destaddr,tx.vout[i].scriptPubKey);
//fprintf(stderr,"%s %.8f ",destaddr,(double)tx.vout[i].nValue/COIN);
vouts.push_back(tx.vout[i]);
}
data << E_MARSHAL(ss << vintxids << vinprevns << vouts << voutpubtxids);
//fprintf(stderr,"numvins.%d numvouts.%d size of data.%d\n",numvins,numvouts,(int32_t)data.size());
hash = Hash(data.begin(),data.end());
memcpy(msg,&hash,sizeof(hash));
return(0);
}
CScript dilithium_registeropret(std::string handle,CPubKey pk,std::vector<uint8_t> bigpub)
{
CScript opret; uint8_t evalcode = EVAL_DILITHIUM;
@@ -2969,6 +3046,24 @@ uint8_t dilithium_spendopretdecode(uint256 &destpubtxid,std::vector<uint8_t> &si
return(0);
}
CScript dilithium_Qsendopret(uint256 destpubtxid,std::vector<uint8_t>sig,std::vector<uint256> voutpubtxids)
{
CScript opret; uint8_t evalcode = EVAL_DILITHIUM;
opret << OP_RETURN << E_MARSHAL(ss << evalcode << 'Q' << destpubtxid << sig << voutpubtxids);
return(opret);
}
uint8_t dilithium_Qsendopretdecode(uint256 &destpubtxid,std::vector<uint8_t>&sig,std::vector<uint256> &voutpubtxids,CScript scriptPubKey)
{
std::vector<uint8_t> vopret; uint8_t e,f;
GetOpReturnData(scriptPubKey,vopret);
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> destpubtxid; ss >> sig; ss >> voutpubtxids) != 0 && e == EVAL_DILITHIUM && f == 'Q' )
{
return(f);
}
return(0);
}
UniValue dilithium_rawtxresult(UniValue &result,std::string rawtx)
{
CTransaction tx;
@@ -3014,14 +3109,17 @@ char *dilithium_hexstr(char *str,uint8_t *buf,int32_t len)
int32_t dilithium_bigpubget(std::string &handle,CPubKey &pk33,uint8_t *pk,uint256 pubtxid)
{
CTransaction tx; uint256 hashBlock; int32_t numvouts; std::vector<uint8_t> bigpub;
if ( myGetTransaction(pubtxid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 1 )
CTransaction tx; uint8_t funcid; uint256 hashBlock; int32_t numvouts=0; std::vector<uint8_t> bigpub;
if ( myGetTransaction(pubtxid,tx,hashBlock) != 0 )
{
if ( dilithium_registeropretdecode(handle,pk33,bigpub,tx.vout[numvouts-1].scriptPubKey) == 'R' && bigpub.size() == CRYPTO_PUBLICKEYBYTES )
if ( (numvouts= tx.vout.size()) > 1 )
{
memcpy(pk,&bigpub[0],CRYPTO_PUBLICKEYBYTES);
return(0);
} else return(-2);
if ( (funcid= dilithium_registeropretdecode(handle,pk33,bigpub,tx.vout[numvouts-1].scriptPubKey)) == 'R' && bigpub.size() == CRYPTO_PUBLICKEYBYTES )
{
memcpy(pk,&bigpub[0],CRYPTO_PUBLICKEYBYTES);
return(0);
} else return(-2);
}
}
return(-1);
}
@@ -3051,12 +3149,20 @@ UniValue dilithium_keypair(uint64_t txfee,struct CCcontract_info *cp,cJSON *para
return(result);
}
CPubKey Faucet_pubkeyget()
{
struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_FAUCET);
return(GetUnspendable(cp,0));
}
UniValue dilithium_register(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
UniValue result(UniValue::VOBJ); std::string rawtx; CPubKey mypk,dilithiumpk; uint8_t seed[SEEDBYTES],pk[CRYPTO_PUBLICKEYBYTES],sk[CRYPTO_SECRETKEYBYTES]; char coinaddr[64],str[CRYPTO_SECRETKEYBYTES*2+1]; std::vector<uint8_t> bigpub; int32_t i,n,warningflag = 0;
UniValue result(UniValue::VOBJ); std::string rawtx; CPubKey faucetpk,mypk,dilithiumpk; uint8_t seed[SEEDBYTES],pk[CRYPTO_PUBLICKEYBYTES],sk[CRYPTO_SECRETKEYBYTES]; char coinaddr[64],str[CRYPTO_SECRETKEYBYTES*2+1]; int64_t CCchange,inputs; std::vector<uint8_t> bigpub; int32_t i,n,warningflag = 0;
if ( txfee == 0 )
txfee = DILITHIUM_TXFEE;
faucetpk = Faucet_pubkeyget();
mypk = pubkey2pk(Mypubkey());
dilithiumpk = GetUnspendable(cp,0);
if ( params != 0 && ((n= cJSON_GetArraySize(params)) == 1 || n == 2) )
@@ -3073,14 +3179,23 @@ UniValue dilithium_register(uint64_t txfee,struct CCcontract_info *cp,cJSON *par
result.push_back(Pair("skaddr",dilithium_addr(coinaddr,sk,CRYPTO_SECRETKEYBYTES)));
for (i=0; i<CRYPTO_PUBLICKEYBYTES; i++)
bigpub.push_back(pk[i]);
if ( AddNormalinputs(mtx,mypk,3*txfee,64) >= 3*txfee )
if ( (inputs= AddCClibtxfee(cp,mtx,dilithiumpk)) > 0 )
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,dilithiumpk));
mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,mypk));
rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,dilithium_registeropret(handle,mypk,bigpub));
return(musig_rawtxresult(result,rawtx));
} else return(cclib_error(result,"couldnt find enough funds"));
} else return(cclib_error(result,"not enough parameters"));
if ( inputs > txfee )
CCchange = (inputs - txfee);
else CCchange = 0;
if ( AddNormalinputs(mtx,mypk,COIN+3*txfee,64) >= 3*txfee )
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,2*txfee,dilithiumpk));
mtx.vout.push_back(MakeCC1vout(cp->evalcode,txfee,mypk));
mtx.vout.push_back(MakeCC1vout(EVAL_FAUCET,COIN,faucetpk));
if ( CCchange != 0 )
mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange,dilithiumpk));
rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,dilithium_registeropret(handle,mypk,bigpub));
return(musig_rawtxresult(result,rawtx));
} else return(cclib_error(result,"couldnt find enough funds"));
} else return(cclib_error(result,"not enough parameters"));
} else return(cclib_error(result,"not dilithiumpk funds"));
}
UniValue dilithium_sign(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
@@ -3169,16 +3284,6 @@ UniValue dilithium_send(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
} else return(cclib_error(result,"not enough parameters"));
}
/*
ultimately what is needed is to be able to scan all utxos to the CC address and be able to spend many vins in the same tx. to do this the opreturn would need to be able to have txid of special with the sigs. However, it is complicated by the need to create a specific message to sign that is the desired outputs and all the inputs. Also, to properly be able to do change and keep everything in dilithium outputs, there needs to be a second destpub.
so the proposed opreturn for spend would be:
destpubtxid0, destpubtxid1 (zeroid if only 1), vector of sigs/sigtxid where if it is len 32 it is a txid that just has the sig in the opreturn.
however, for now, to keep things simple we will only support spending a specific txid to normal output to avoid needing a combined opreturn and other complications.
*/
UniValue dilithium_spend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
@@ -3229,10 +3334,320 @@ UniValue dilithium_spend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params
} else return(cclib_error(result,"need to have exactly 2 params sendtxid, scriptPubKey"));
}
int64_t dilithium_inputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,uint256 destpubtxid,int64_t total,int32_t maxinputs,char *cmpaddr)
{
char coinaddr[64]; int64_t threshold,nValue,price,totalinputs = 0; uint256 checktxid,txid,hashBlock; std::vector<uint8_t> origpubkey,tmpsig; CTransaction vintx; int32_t vout,numvouts,n = 0; std::vector<uint256> voutpubtxids;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
GetCCaddress(cp,coinaddr,pk);
SetCCunspents(unspentOutputs,coinaddr);
if ( maxinputs > CC_MAXVINS )
maxinputs = CC_MAXVINS;
if ( maxinputs > 0 )
threshold = total/maxinputs;
else threshold = total;
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
txid = it->first.txhash;
vout = (int32_t)it->first.index;
//char str[65]; fprintf(stderr,"%s check %s/v%d %.8f vs %.8f\n",coinaddr,uint256_str(str,txid),vout,(double)it->second.satoshis/COIN,(double)threshold/COIN);
if ( it->second.satoshis < threshold || it->second.satoshis == DILITHIUM_TXFEE )
continue;
if ( GetTransaction(txid,vintx,hashBlock,false) != 0 && (numvouts= vintx.vout.size()) > 1 )
{
if ( (nValue= IsCClibvout(cp,vintx,vout,cmpaddr)) > DILITHIUM_TXFEE && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 )
{
if ( (dilithium_Qsendopretdecode(checktxid,tmpsig,voutpubtxids,vintx.vout[numvouts-1].scriptPubKey) == 'Q' && vout < voutpubtxids.size() && destpubtxid == voutpubtxids[vout]) || (dilithium_sendopretdecode(checktxid,vintx.vout[numvouts-1].scriptPubKey) == 'x' && destpubtxid == checktxid) )
{
if ( total != 0 && maxinputs != 0 )
mtx.vin.push_back(CTxIn(txid,vout,CScript()));
nValue = it->second.satoshis;
totalinputs += nValue;
n++;
if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) )
break;
}
} //else fprintf(stderr,"nValue %.8f too small or already spent in mempool\n",(double)nValue/COIN);
} else fprintf(stderr,"couldnt get tx\n");
}
return(totalinputs);
}
UniValue dilithium_Qsend(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
UniValue result(UniValue::VOBJ); std::string rawtx; CPubKey mypk,destpub33; CTransaction tx,vintx; uint256 prevhash,mypubtxid,hashBlock,destpubtxid; int64_t amount,inputsum,outputsum,change; int32_t i,smlen,n,numvouts; char str[129],myCCaddr[64],*scriptstr; CTxOut vout; std::string handle; uint8_t pk[CRYPTO_PUBLICKEYBYTES],pk2[CRYPTO_PUBLICKEYBYTES],sk[CRYPTO_SECRETKEYBYTES],msg[32],seed[32]; std::vector<uint8_t> sig; std::vector<uint256> voutpubtxids;
if ( txfee == 0 )
txfee = DILITHIUM_TXFEE;
mypk = pubkey2pk(Mypubkey());
GetCCaddress(cp,myCCaddr,mypk);
if ( params != 0 && (n= cJSON_GetArraySize(params)) >= 4 && (n & 1) == 0 )
{
mypubtxid = juint256(jitem(params,0));
if ( cclib_parsehash(seed,jitem(params,1),32) < 0 )
{
Myprivkey(seed);
result.push_back(Pair("warning","test mode using privkey for -pubkey, only for testing. there is no point using quantum secure signing if you are using a privkey with a known secp256k1 pubkey!!"));
}
_dilithium_keypair(pk,sk,seed);
outputsum = 0;
for (i=2; i<n; i+=2)
{
amount = jdouble(jitem(params,i+1),0)*COIN + 0.0000000049;
scriptstr = jstr(jitem(params,i),0);
if ( is_hexstr(scriptstr,0) == 64 )
{
prevhash = juint256(jitem(params,i));
if ( dilithium_bigpubget(handle,destpub33,pk2,prevhash) < 0 )
{
result.push_back(Pair("destpubtxid",prevhash.GetHex().c_str()));
return(cclib_error(result,"couldnt find bigpub at destpubtxid"));
}
else
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,amount,destpub33));
voutpubtxids.push_back(prevhash); // binds destpub22 CC addr with dilithium bigpub
}
}
else
{
CScript scriptPubKey;
scriptPubKey.resize(strlen(scriptstr)/2);
decode_hex(&scriptPubKey[0],strlen(scriptstr)/2,scriptstr);
vout.nValue = amount;
vout.scriptPubKey = scriptPubKey;
mtx.vout.push_back(vout);
voutpubtxids.push_back(zeroid);
}
outputsum += amount;
}
if ( (inputsum= dilithium_inputs(cp,mtx,mypk,mypubtxid,outputsum+txfee,64,myCCaddr)) >= outputsum+txfee )
{
change = (inputsum - outputsum - txfee);
if ( change >= txfee )
{
mtx.vout.push_back(MakeCC1vout(cp->evalcode,change,mypk));
voutpubtxids.push_back(mypubtxid);
}
tx = mtx;
dilithium_Qmsghash(msg,tx,(int32_t)voutpubtxids.size(),voutpubtxids);
//for (i=0; i<32; i++)
// fprintf(stderr,"%02x",msg[i]);
//fprintf(stderr," msg\n");
sig.resize(32+CRYPTO_BYTES);
if ( dilithium_bigpubget(handle,destpub33,pk2,mypubtxid) < 0 )
return(cclib_error(result,"couldnt get bigpub"));
else if ( memcmp(pk,pk2,sizeof(pk)) != 0 )
return(cclib_error(result,"dilithium bigpub mismatch"));
else if ( destpub33 != mypk )
return(cclib_error(result,"destpub33 is not for this -pubkey"));
else if ( _dilithium_sign(&sig[0],&smlen,msg,32,sk) < 0 )
return(cclib_error(result,"dilithium signing error"));
else if ( smlen != 32+CRYPTO_BYTES )
return(cclib_error(result,"siglen error"));
rawtx = FinalizeCCTx(0,cp,mtx,mypk,txfee,dilithium_Qsendopret(mypubtxid,sig,voutpubtxids));
return(dilithium_rawtxresult(result,rawtx));
} else return(cclib_error(result,"Q couldnt find enough Q or x inputs"));
} else return(cclib_error(result,"need to have exactly 2 params sendtxid, scriptPubKey"));
}
bool dilithium_Qvalidate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx)
{
int32_t i,numvins,numvouts,mlen,smlen=CRYPTO_BYTES+32; CPubKey destpub33; std::string handle; uint256 tmptxid,hashBlock,destpubtxid,signerpubtxid; CTransaction vintx; std::vector<uint8_t> tmpsig,sig,vopret; uint8_t msg[32],msg2[CRYPTO_BYTES+32],pk[CRYPTO_PUBLICKEYBYTES],*script; std::vector<uint256> voutpubtxids;
numvins = tx.vin.size();
signerpubtxid = zeroid;
for (i=0; i<numvins; i++)
{
if ( IsCCInput(tx.vin[i].scriptSig) != 0 )
{
if ( myGetTransaction(tx.vin[i].prevout.hash,vintx,hashBlock) != 0 && (numvouts= vintx.vout.size()) > 1 )
{
GetOpReturnData(vintx.vout[numvouts-1].scriptPubKey,vopret);
script = (uint8_t *)vopret.data();
if ( script[1] == 'Q' )
{
if ( dilithium_Qsendopretdecode(tmptxid,tmpsig,voutpubtxids,vintx.vout[numvouts-1].scriptPubKey) != 'Q' )
return eval->Invalid("couldnt decode destpubtxid from Qsend");
else if ( tx.vin[i].prevout.n > voutpubtxids.size() )
return eval->Invalid("no destpubtxid for prevout.n");
destpubtxid = voutpubtxids[tx.vin[i].prevout.n];
}
else
{
if ( dilithium_sendopretdecode(destpubtxid,vintx.vout[numvouts-1].scriptPubKey) != 'x' )
return eval->Invalid("couldnt decode destpubtxid from send");
}
if ( signerpubtxid == zeroid )
signerpubtxid = destpubtxid;
else if ( destpubtxid != signerpubtxid )
return eval->Invalid("destpubtxid of vini doesnt match first one");
}
}
}
if ( signerpubtxid != zeroid )
{
numvouts = tx.vout.size();
if ( dilithium_Qsendopretdecode(destpubtxid,sig,voutpubtxids,tx.vout[numvouts-1].scriptPubKey) == 'Q' && destpubtxid == signerpubtxid && sig.size() == smlen )
{
if ( dilithium_Qmsghash(msg,tx,numvouts-1,voutpubtxids) < 0 )
return eval->Invalid("couldnt get Qmsghash");
else if ( dilithium_bigpubget(handle,destpub33,pk,signerpubtxid) < 0 )
return eval->Invalid("couldnt get bigpub");
else
{
if ( _dilithium_verify(msg2,&mlen,&sig[0],smlen,pk) < 0 )
return eval->Invalid("failed dilithium verify");
else if ( mlen != 32 || memcmp(msg,msg2,32) != 0 )
{
for (i=0; i<32; i++)
fprintf(stderr,"%02x",msg[i]);
fprintf(stderr," vs ");
for (i=0; i<mlen; i++)
fprintf(stderr,"%02x",msg2[i]);
fprintf(stderr,"mlen.%d\n",mlen);
return eval->Invalid("failed dilithium msg verify");
}
else return true;
}
} else return eval->Invalid("failed decode Qsend");
} else return eval->Invalid("unexpected zero signerpubtxid");
}
int32_t dilithium_registrationpub33(char *pkaddr,CPubKey &pub33,uint256 txid)
{
std::string handle; std::vector<uint8_t> bigpub; CTransaction tx; uint256 hashBlock; int32_t numvouts;
pkaddr[0] = 0;
if ( myGetTransaction(txid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 1 )
{
if ( dilithium_registeropretdecode(handle,pub33,bigpub,tx.vout[numvouts-1].scriptPubKey) == 'R' )
{
dilithium_addr(pkaddr,&bigpub[0],CRYPTO_PUBLICKEYBYTES);
return(0);
}
}
return(-1);
}
void dilithium_handleinit(struct CCcontract_info *cp)
{
static int32_t didinit;
std::vector<std::pair<CAddressIndexKey, CAmount> > txids; struct dilithium_handle *hashstr; CPubKey dilithiumpk,pub33; uint256 txid,hashBlock; CTransaction txi; int32_t numvouts; std::vector<uint8_t> bigpub; std::string handle; char CCaddr[64];
if ( didinit != 0 )
return;
pthread_mutex_init(&DILITHIUM_MUTEX,NULL);
dilithiumpk = GetUnspendable(cp,0);
GetCCaddress(cp,CCaddr,dilithiumpk);
SetCCtxids(txids,CCaddr);
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=txids.begin(); it!=txids.end(); it++)
{
txid = it->first.txhash;
if ( myGetTransaction(txid,txi,hashBlock) != 0 && (numvouts= txi.vout.size()) > 1 )
{
if ( dilithium_registeropretdecode(handle,pub33,bigpub,txi.vout[numvouts-1].scriptPubKey) == 'R' )
{
if ( (hashstr= dilithium_handlenew((char *)handle.c_str())) != 0 )
{
if ( hashstr->destpubtxid != txid )
{
if ( hashstr->destpubtxid != zeroid )
fprintf(stderr,"overwriting %s %s with %s\n",handle.c_str(),hashstr->destpubtxid.GetHex().c_str(),txid.GetHex().c_str());
fprintf(stderr,"%s <- %s\n",handle.c_str(),txid.GetHex().c_str());
hashstr->destpubtxid = txid;
}
}
}
}
}
didinit = 1;
}
UniValue dilithium_handleinfo(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
UniValue result(UniValue::VOBJ); CPubKey pub33; int32_t i,n; char *handlestr,pkaddr[64],str[67]; struct dilithium_handle *hashstr;
if ( params != 0 && (n= cJSON_GetArraySize(params)) == 1 )
{
dilithium_handleinit(cp);
if ( (handlestr= jstr(jitem(params,0),0)) != 0 )
{
result.push_back(Pair("result","success"));
result.push_back(Pair("handle",handlestr));
if ( (hashstr= dilithium_handlefind(handlestr)) != 0 )
{
result.push_back(Pair("destpubtxid",hashstr->destpubtxid.GetHex().c_str()));
if ( dilithium_registrationpub33(pkaddr,pub33,hashstr->destpubtxid) == 0 )
{
for (i=0; i<33; i++)
sprintf(&str[i<<1],"%02x",((uint8_t *)pub33.begin())[i]);
str[i<<1] = 0;
result.push_back(Pair("pkaddr",pkaddr));
}
result.push_back(Pair("pubkey",str));
} else result.push_back(Pair("status","available"));
return(result);
}
}
result.push_back(Pair("result","error"));
return(result);
}
bool dilithium_Rvalidate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx)
{
static int32_t didinit;
uint256 txid; int32_t numvouts; struct dilithium_handle *hashstr; std::string handle; std::vector<uint8_t> bigpub; CPubKey oldpub33,pub33,dilithiumpk; CTxOut vout,vout0; char pkaddr[64];
if ( height < 14500 )
return(true);
dilithium_handleinit(cp);
dilithiumpk = GetUnspendable(cp,0);
if ( (numvouts= tx.vout.size()) <= 1 )
return eval->Invalid("not enough vouts for registration tx");
else if ( dilithium_registeropretdecode(handle,pub33,bigpub,tx.vout[numvouts-1].scriptPubKey) == 'R' )
{
// relies on all current block tx to be put into mempool
txid = tx.GetHash();
vout0 = MakeCC1vout(cp->evalcode,2*DILITHIUM_TXFEE,dilithiumpk);
vout = MakeCC1vout(EVAL_FAUCET,COIN,Faucet_pubkeyget());
if ( tx.vout[0] != vout0 )
return eval->Invalid("mismatched vout0 for register");
else if ( tx.vout[1].nValue != DILITHIUM_TXFEE )
return eval->Invalid("vout1 for register not txfee");
else if ( tx.vout[2] != vout )
return eval->Invalid("register not sending to faucet");
else if ( (hashstr= dilithium_handlenew((char *)handle.c_str())) == 0 )
return eval->Invalid("error creating dilithium handle");
else if ( hashstr->destpubtxid == zeroid )
{
hashstr->destpubtxid = txid;
return(true);
}
else
{
if ( hashstr->destpubtxid == txid )
return(true);
else if ( dilithium_registrationpub33(pkaddr,oldpub33,hashstr->destpubtxid) == 0 )
{
if ( oldpub33 == pub33 )
{
hashstr->destpubtxid = txid;
fprintf(stderr,"ht.%d %s <- %s\n",height,handle.c_str(),txid.GetHex().c_str());
return(true);
}
}
return eval->Invalid("duplicate dilithium handle rejected");
}
} else return eval->Invalid("couldnt decode register opret");
}
bool dilithium_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx)
{
CPubKey destpub33; std::string handle; uint256 hashBlock,destpubtxid,checktxid; CTransaction vintx; int32_t numvouts,mlen,smlen=CRYPTO_BYTES+32; std::vector<uint8_t> sig; uint8_t msg[32],msg2[CRYPTO_BYTES+32],pk[CRYPTO_PUBLICKEYBYTES];
if ( tx.vout.size() != 2 )
CPubKey destpub33; std::string handle; uint256 hashBlock,destpubtxid,checktxid; CTransaction vintx; int32_t numvouts,mlen,smlen=CRYPTO_BYTES+32; std::vector<uint8_t> sig,vopret; uint8_t msg[32],msg2[CRYPTO_BYTES+32],pk[CRYPTO_PUBLICKEYBYTES],*script;
// if all dilithium tx -> do multispend/send, else:
numvouts = tx.vout.size();
GetOpReturnData(tx.vout[numvouts-1].scriptPubKey,vopret);
script = (uint8_t *)vopret.data();
if ( script[1] == 'R' )
return(dilithium_Rvalidate(cp,height,eval,tx));
else if ( script[1] == 'Q' )
return(dilithium_Qvalidate(cp,height,eval,tx));
else if ( tx.vout.size() != 2 )
return eval->Invalid("numvouts != 2");
else if ( tx.vin.size() != 1 )
return eval->Invalid("numvins != 1");

View File

@@ -154,46 +154,17 @@ int32_t Eval::GetNotaries(uint8_t pubkeys[64][33], int32_t height, uint32_t time
return komodo_notaries(pubkeys, height, timestamp);
}
bool Eval::CheckNotaryInputs(const CTransaction &tx, uint32_t height, uint32_t timestamp) const
{
if (tx.vin.size() < 11) return false;
uint8_t seenNotaries[64] = {0};
uint8_t notaries[64][33];
int nNotaries = GetNotaries(notaries, height, timestamp);
CrosschainAuthority auth;
auth.requiredSigs = 11;
auth.size = GetNotaries(auth.notaries, height, timestamp);
BOOST_FOREACH(const CTxIn &txIn, tx.vin)
{
// Get notary pubkey
CTransaction tx;
uint256 hashBlock;
if (!GetTxUnconfirmed(txIn.prevout.hash, tx, hashBlock)) return false;
if (tx.vout.size() < txIn.prevout.n) return false;
CScript spk = tx.vout[txIn.prevout.n].scriptPubKey;
if (spk.size() != 35) return false;
std::vector<unsigned char> scriptVec = std::vector<unsigned char>(spk.begin(),spk.end());
const unsigned char *pk = scriptVec.data();
if (pk++[0] != 33) return false;
if (pk[33] != OP_CHECKSIG) return false;
// Check it's a notary
for (int i=0; i<nNotaries; i++) {
if (!seenNotaries[i]) {
if (memcmp(pk, notaries[i], 33) == 0) {
seenNotaries[i] = 1;
goto found;
}
}
}
return false;
found:;
}
return true;
return CheckTxAuthority(tx, auth);
}
/*
* Get MoM from a notarisation tx hash (on KMD)
*/

View File

@@ -146,7 +146,11 @@ int64_t AddFaucetInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPub
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
GetCCaddress(cp,coinaddr,pk);
SetCCunspents(unspentOutputs,coinaddr);
threshold = total/(maxinputs+1);
if ( maxinputs > CC_MAXVINS )
maxinputs = CC_MAXVINS;
if ( maxinputs > 0 )
threshold = total/maxinputs;
else threshold = total;
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
txid = it->first.txhash;

View File

@@ -157,19 +157,21 @@ CScript EncodeGatewaysBindOpRet(uint8_t funcid,uint256 tokenid,std::string coin,
{
CScript opret; uint8_t evalcode = EVAL_GATEWAYS; struct CCcontract_info *cp,C; CPubKey gatewayspk;
std::vector<CPubKey> pubkeys;
vscript_t vopret;
cp = CCinit(&C,EVAL_GATEWAYS);
gatewayspk = GetUnspendable(cp,0);
pubkeys.push_back(gatewayspk);
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << coin << totalsupply << oracletxid << M << N << gatewaypubkeys << taddr << prefix << prefix2 << wiftype);
return(EncodeTokenOpRet(tokenid,pubkeys,opret));
vopret = E_MARSHAL(ss << evalcode << funcid << coin << totalsupply << oracletxid << M << N << gatewaypubkeys << taddr << prefix << prefix2 << wiftype);
return(EncodeTokenOpRet(tokenid,pubkeys, std::make_pair(OPRETID_GATEWAYSDATA, vopret)));
}
uint8_t DecodeGatewaysBindOpRet(char *depositaddr,const CScript &scriptPubKey,uint256 &tokenid,std::string &coin,int64_t &totalsupply,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector<CPubKey> &gatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t wiftype)
uint8_t DecodeGatewaysBindOpRet(char *depositaddr,const CScript &scriptPubKey,uint256 &tokenid,std::string &coin,int64_t &totalsupply,uint256 &oracletxid,uint8_t &M,uint8_t &N,std::vector<CPubKey> &gatewaypubkeys,uint8_t &taddr,uint8_t &prefix,uint8_t &prefix2,uint8_t &wiftype)
{
std::vector<std::pair<uint8_t, vscript_t>> oprets;
std::vector<uint8_t> vopret,vOpretExtra; uint8_t *script,e,f,tokenevalcode; std::vector<CPubKey> pubkeys;
if (DecodeTokenOpRet(scriptPubKey,tokenevalcode,tokenid,pubkeys,vOpretExtra)!=0 && tokenevalcode==EVAL_TOKENS && vOpretExtra.size()>0)
if (DecodeTokenOpRet(scriptPubKey,tokenevalcode,tokenid,pubkeys,oprets)!=0 && GetOpretBlob(oprets, OPRETID_GATEWAYSDATA, vOpretExtra) && tokenevalcode==EVAL_TOKENS && vOpretExtra.size()>0)
{
vopret=vOpretExtra;
}
@@ -183,7 +185,7 @@ uint8_t DecodeGatewaysBindOpRet(char *depositaddr,const CScript &scriptPubKey,ui
if ( N > 1 )
{
strcpy(depositaddr,CBitcoinAddress(CScriptID(GetScriptForMultisig(M,gatewaypubkeys))).ToString().c_str());
LogPrint("gatewayscc-1","f.%c M.%d of N.%d size.%d -> %s\n",f,M,N,(int32_t)gatewaypubkeys.size(),depositaddr);
LOGSTREAM("gatewayscc", CCLOG_DEBUG1, stream << "f." << f << " M." << M << " of N." << N << " size." << (int32_t)gatewaypubkeys.size() << " -> " << depositaddr << std::endl);
} else Getscriptaddress(depositaddr,CScript() << ParseHex(HexStr(gatewaypubkeys[0])) << OP_CHECKSIG);
}
else
@@ -192,7 +194,7 @@ uint8_t DecodeGatewaysBindOpRet(char *depositaddr,const CScript &scriptPubKey,ui
else GetCustomscriptaddress(depositaddr,CScript() << ParseHex(HexStr(gatewaypubkeys[0])) << OP_CHECKSIG,taddr,prefix,prefix2);
}
return(f);
} else LogPrint("gatewayscc-1","error decoding bind opret\n");
} else LOGSTREAM("gatewayscc",CCLOG_DEBUG1, stream << "error decoding bind opret" << std::endl);
return(0);
}
@@ -221,17 +223,19 @@ CScript EncodeGatewaysClaimOpRet(uint8_t funcid,uint256 tokenid,uint256 bindtxid
{
CScript opret; uint8_t evalcode = EVAL_GATEWAYS; struct CCcontract_info *cp,C; CPubKey gatewayspk;
std::vector<CPubKey> pubkeys;
vscript_t vopret;
pubkeys.push_back(destpub);
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << bindtxid << refcoin << deposittxid << destpub << amount);
return(EncodeTokenOpRet(tokenid,pubkeys,opret));
vopret = /*<< OP_RETURN <<*/ E_MARSHAL(ss << evalcode << funcid << bindtxid << refcoin << deposittxid << destpub << amount);
return(EncodeTokenOpRet(tokenid,pubkeys, make_pair(OPRETID_GATEWAYSDATA, vopret)));
}
uint8_t DecodeGatewaysClaimOpRet(const CScript &scriptPubKey,uint256 &tokenid,uint256 &bindtxid,std::string &refcoin,uint256 &deposittxid,CPubKey &destpub,int64_t &amount)
{
std::vector<std::pair<uint8_t, vscript_t>> oprets;
std::vector<uint8_t> vopret,vOpretExtra; uint8_t *script,e,f,tokenevalcode; std::vector<CPubKey> pubkeys;
if (DecodeTokenOpRet(scriptPubKey,tokenevalcode,tokenid,pubkeys,vOpretExtra)!=0 && tokenevalcode==EVAL_TOKENS && vOpretExtra.size()>0)
if (DecodeTokenOpRet(scriptPubKey,tokenevalcode,tokenid,pubkeys, oprets)!=0 && GetOpretBlob(oprets, OPRETID_GATEWAYSDATA, vOpretExtra) && tokenevalcode==EVAL_TOKENS && vOpretExtra.size()>0)
{
vopret=vOpretExtra;
}
@@ -248,19 +252,21 @@ CScript EncodeGatewaysWithdrawOpRet(uint8_t funcid,uint256 tokenid,uint256 bindt
{
CScript opret; uint8_t evalcode = EVAL_GATEWAYS; struct CCcontract_info *cp,C; CPubKey gatewayspk;
std::vector<CPubKey> pubkeys;
vscript_t vopret;
cp = CCinit(&C,EVAL_GATEWAYS);
gatewayspk = GetUnspendable(cp,0);
pubkeys.push_back(gatewayspk);
opret << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << bindtxid << refcoin << withdrawpub << amount);
return(EncodeTokenOpRet(tokenid,pubkeys,opret));
vopret = /*opret << OP_RETURN << */ E_MARSHAL(ss << evalcode << funcid << bindtxid << refcoin << withdrawpub << amount);
return(EncodeTokenOpRet(tokenid,pubkeys, std::make_pair(OPRETID_GATEWAYSDATA, vopret)));
}
uint8_t DecodeGatewaysWithdrawOpRet(const CScript &scriptPubKey, uint256& tokenid, uint256 &bindtxid, std::string &refcoin, CPubKey &withdrawpub, int64_t &amount)
{
std::vector<std::pair<uint8_t, vscript_t>> oprets;
std::vector<uint8_t> vopret,vOpretExtra; uint8_t *script,e,f,tokenevalcode; std::vector<CPubKey> pubkeys;
if (DecodeTokenOpRet(scriptPubKey,tokenevalcode,tokenid,pubkeys,vOpretExtra)!=0 && tokenevalcode==EVAL_TOKENS && vOpretExtra.size()>0)
if (DecodeTokenOpRet(scriptPubKey,tokenevalcode,tokenid,pubkeys, oprets)!=0 && GetOpretBlob(oprets, OPRETID_GATEWAYSDATA, vOpretExtra) && tokenevalcode==EVAL_TOKENS && vOpretExtra.size()>0)
{
vopret=vOpretExtra;
}
@@ -336,9 +342,10 @@ uint8_t DecodeGatewaysMarkDoneOpRet(const CScript &scriptPubKey, uint256 &withdr
uint8_t DecodeGatewaysOpRet(const CScript &scriptPubKey)
{
std::vector<std::pair<uint8_t, vscript_t>> oprets;
std::vector<uint8_t> vopret,vOpretExtra; uint8_t *script,e,f,tokenevalcode; std::vector<CPubKey> pubkeys; uint256 tokenid;
if (DecodeTokenOpRet(scriptPubKey,tokenevalcode,tokenid,pubkeys,vOpretExtra)!=0 && tokenevalcode==EVAL_TOKENS && vOpretExtra.size()>0)
if (DecodeTokenOpRet(scriptPubKey,tokenevalcode,tokenid,pubkeys, oprets)!=0 && GetOpretBlob(oprets, OPRETID_GATEWAYSDATA, vOpretExtra) && tokenevalcode==EVAL_TOKENS && vOpretExtra.size()>0)
{
vopret=vOpretExtra;
}
@@ -374,15 +381,15 @@ bool GatewaysExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransacti
numvouts = tx.vout.size();
for (i=0; i<numvins; i++)
{
//LogPrint("gatewayscc","vini.%d\n",i);
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "vini." << i << std::endl);
if ( (*cp->ismyvin)(tx.vin[i].scriptSig) != 0 )
{
//LogPrint("gatewayscc","vini.%d check mempool\n",i);
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "vini." << i << " check mempool" << std::endl);
if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 )
return eval->Invalid("cant find vinTx");
else
{
//LogPrint("gatewayscc","vini.%d check hash and vout\n",i);
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "vini." << i << " check hash and vout" << std::endl);
if ( hashBlock == zerohash )
return eval->Invalid("cant Gateways from mempool");
if ( (assetoshis= IsGatewaysvout(cp,vinTx,tx.vin[i].prevout.n)) != 0 )
@@ -392,13 +399,13 @@ bool GatewaysExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransacti
}
for (i=0; i<numvouts; i++)
{
//LogPrint("gatewayscc","i.%d of numvouts.%d\n",i,numvouts);
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "i." << i << " of numvouts." << numvouts << std::endl);
if ( (assetoshis= IsGatewaysvout(cp,tx,i)) != 0 )
outputs += assetoshis;
}
if ( inputs != outputs+txfee )
{
LogPrint("gatewayscc","inputs %llu vs outputs %llu\n",(long long)inputs,(long long)outputs);
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << "inputs " << (long long)inputs << " vs outputs " << (long long)outputs << std::endl);
return eval->Invalid("mismatched inputs != outputs + txfee");
}
else return(true);
@@ -418,7 +425,7 @@ static int32_t myIs_coinaddr_inmempoolvout(char *coinaddr)
Getscriptaddress(destaddr,tx.vout[i].scriptPubKey);
if ( strcmp(destaddr,coinaddr) == 0 )
{
LogPrint("gatewayscc-1","found (%s) vout in mempool\n",coinaddr);
LOGSTREAM("gatewayscc",CCLOG_DEBUG1, stream << "found (" << coinaddr << ") vout in mempool" << std::endl);
return(1);
}
}
@@ -431,36 +438,35 @@ uint256 GatewaysReverseScan(uint256 &txid,int32_t height,uint256 reforacletxid,u
{
CTransaction tx; uint256 hash,mhash,bhash,hashBlock,oracletxid; int32_t len,len2,numvouts; int64_t val,merkleht; CPubKey pk; std::vector<uint8_t>data;
txid = zeroid;
char str[65];
LogPrint("gatewayscc-2","start reverse scan %s\n",uint256_str(str,batontxid));
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "start reverse scan " << batontxid.GetHex() << std::endl);
while ( myGetTransaction(batontxid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 0 )
{
LogPrint("gatewayscc-2","check %s\n",uint256_str(str,batontxid));
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "check " << batontxid.GetHex() << std::endl);
if ( DecodeOraclesData(tx.vout[numvouts-1].scriptPubKey,oracletxid,bhash,pk,data) == 'D' && oracletxid == reforacletxid )
{
LogPrint("gatewayscc-2","decoded %s\n",uint256_str(str,batontxid));
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "decoded " << batontxid.GetHex() << std::endl);
if ( oracle_format(&hash,&merkleht,0,'I',(uint8_t *)data.data(),0,(int32_t)data.size()) == sizeof(int32_t) && merkleht == height )
{
len = oracle_format(&hash,&val,0,'h',(uint8_t *)data.data(),sizeof(int32_t),(int32_t)data.size());
len2 = oracle_format(&mhash,&val,0,'h',(uint8_t *)data.data(),(int32_t)(sizeof(int32_t)+sizeof(uint256)),(int32_t)data.size());
char str2[65]; LogPrint("gatewayscc","found merkleht.%d len.%d len2.%d %s %s\n",(int32_t)merkleht,len,len2,uint256_str(str,hash),uint256_str(str2,mhash));
LOGSTREAM("gatewayscc",CCLOG_DEBUG1, stream << "found merkleht." << (int32_t)merkleht << " len." << len << " len2." << len2 << " " << hash.GetHex() << " " << mhash.GetHex() << std::endl);
if ( len == sizeof(hash)+sizeof(int32_t) && len2 == 2*sizeof(mhash)+sizeof(int32_t) && mhash != zeroid )
{
txid = batontxid;
LogPrint("gatewayscc-2","set txid\n");
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "set txid" << std::endl);
return(mhash);
}
else
{
LogPrint("gatewayscc-2","missing hash\n");
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "missing hash" << std::endl);
return(zeroid);
}
} else LogPrint("gatewayscc-2","height.%d vs search ht.%d\n",(int32_t)merkleht,(int32_t)height);
} else LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "height." << (int32_t)merkleht << " vs search ht." << (int32_t)height << std::endl);
batontxid = bhash;
LogPrint("gatewayscc-2","new hash %s\n",uint256_str(str,batontxid));
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "new hash " << batontxid.GetHex() << std::endl);
} else break;
}
LogPrint("gatewayscc-2","end of loop\n");
LOGSTREAM("gatewayscc",CCLOG_DEBUG2, stream << "end of loop\n");
return(zeroid);
}
@@ -493,27 +499,27 @@ uint256 BitcoinGetProofMerkleRoot(const std::vector<uint8_t> &proofData, std::ve
int64_t GatewaysVerify(char *refdepositaddr,uint256 oracletxid,int32_t claimvout,std::string refcoin,uint256 cointxid,const std::string deposithex,std::vector<uint8_t>proof,uint256 merkleroot,CPubKey destpub,uint8_t taddr,uint8_t prefix,uint8_t prefix2)
{
std::vector<uint256> txids; uint256 proofroot,hashBlock,txid = zeroid; CTransaction tx; std::string name,description,format;
char destaddr[64],destpubaddr[64],claimaddr[64],str[65],str2[65]; int32_t i,numvouts; int64_t nValue = 0;
char destaddr[64],destpubaddr[64],claimaddr[64]; int32_t i,numvouts; int64_t nValue = 0;
if ( myGetTransaction(oracletxid,tx,hashBlock) == 0 || (numvouts= tx.vout.size()) <= 0 )
{
LogPrint("gatewayscc","GatewaysVerify cant find oracletxid %s\n",uint256_str(str,oracletxid));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << "GatewaysVerify cant find oracletxid " << oracletxid.GetHex() << std::endl);
return(0);
}
if ( DecodeOraclesCreateOpRet(tx.vout[numvouts-1].scriptPubKey,name,description,format) != 'C' || name != refcoin )
{
LogPrint("gatewayscc","GatewaysVerify mismatched oracle name %s != %s\n",name.c_str(),refcoin.c_str());
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << "GatewaysVerify mismatched oracle name " << name << " != " << refcoin << std::endl);
return(0);
}
proofroot = BitcoinGetProofMerkleRoot(proof,txids);
if ( proofroot != merkleroot )
{
LogPrint("gatewayscc","GatewaysVerify mismatched merkleroot %s != %s\n",uint256_str(str,proofroot),uint256_str(str2,merkleroot));
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << "GatewaysVerify mismatched merkleroot " << proofroot.GetHex() << " != " << merkleroot.GetHex() << std::endl);
return(0);
}
if (std::find(txids.begin(), txids.end(), cointxid) == txids.end())
{
LogPrint("gatewayscc", "GatewaysVerify invalid proof for this cointxid\n");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << "GatewaysVerify invalid proof for this cointxid" << std::endl);
return 0;
}
if ( DecodeHexTx(tx,deposithex) != 0 )
@@ -534,10 +540,10 @@ int64_t GatewaysVerify(char *refdepositaddr,uint256 oracletxid,int32_t claimvout
}
if ( txid == cointxid )
{
LogPrint("gatewayscc-1","verified proof for cointxid in merkleroot\n");
LOGSTREAM("gatewayscc",CCLOG_DEBUG1, stream << "verified proof for cointxid in merkleroot" << std::endl);
return(nValue);
} else LogPrint("gatewayscc","(%s) != (%s) or txid %s mismatch.%d or script mismatch\n",refdepositaddr,destaddr,uint256_str(str,txid),txid != cointxid);
} else LogPrint("gatewayscc","claimaddr.(%s) != destpubaddr.(%s)\n",claimaddr,destpubaddr);
} else LOGSTREAM("gatewayscc",CCLOG_INFO, stream << "(" << refdepositaddr << ") != (" << destaddr << ") or txid " << txid.GetHex() << " mismatch." << (txid!=cointxid) << " or script mismatch" << std::endl);
} else LOGSTREAM("gatewayscc",CCLOG_INFO, stream << "claimaddr." << claimaddr << " != destpubaddr." << destpubaddr << std::endl);
}
return(0);
}
@@ -571,7 +577,7 @@ int32_t GatewaysBindExists(struct CCcontract_info *cp,CPubKey gatewayspk,uint256
{
if ( tokenid == reftokenid )
{
LogPrint("gatewayscc","trying to bind an existing tokenid\n");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << "trying to bind an existing tokenid" << std::endl);
return(1);
}
}
@@ -869,7 +875,7 @@ bool GatewaysValidate(struct CCcontract_info *cp,Eval *eval,const CTransaction &
}
retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts);
if ( retval != 0 )
LogPrint("gatewayscc","Gateways tx validated\n");
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << "Gateways tx validated" << std::endl);
else fprintf(stderr,"Gateways tx invalid\n");
return(retval);
// }
@@ -892,8 +898,12 @@ int64_t AddGatewaysInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CP
{
GetTokensCCaddress(cp,coinaddr,pk);
SetCCunspents(unspentOutputs,coinaddr);
threshold = total/(maxinputs+1);
LogPrint("gatewayscc-1","check %s for gateway inputs\n",coinaddr);
if ( maxinputs > CC_MAXVINS )
maxinputs = CC_MAXVINS;
if ( maxinputs > 0 )
threshold = total/maxinputs;
else threshold = total;
LOGSTREAM("gatewayscc",CCLOG_DEBUG1, stream << "check " << coinaddr << " for gateway inputs" << std::endl);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
txid = it->first.txhash;
@@ -928,9 +938,9 @@ int64_t AddGatewaysInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CP
}
return(totalinputs);
}
else LogPrint("gatewayscc","invalid GatewaysBind\n");
else LOGSTREAM("gatewayscc",CCLOG_INFO, stream << "invalid GatewaysBind" << std::endl);
}
else LogPrint("gatewayscc","can't find GatewaysBind txid\n");
else LOGSTREAM("gatewayscc",CCLOG_INFO, stream << "can't find GatewaysBind txid" << std::endl);
return(0);
}
@@ -956,18 +966,18 @@ std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t
prefix2 = p2;
wiftype = p3;
taddr = p4;
LogPrint("gatewayscc-1","set prefix %d, prefix2 %d, wiftype %d for %s\n",prefix,prefix2,wiftype,coin.c_str());
LOGSTREAM("gatewayscc",CCLOG_DEBUG1, stream << "set prefix " << prefix << ", prefix2 " << prefix2 << ", wiftype " << wiftype << ", taddr " << taddr << " for " << coin << std::endl);
}
if ( N == 0 || N > 15 || M > N )
{
CCerror = strprintf("illegal M.%d or N.%d",M,N);
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( pubkeys.size() != N )
{
CCerror = strprintf("M.%d N.%d but pubkeys[%d]",M,N,(int32_t)pubkeys.size());
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
for (i=0; i<N; i++)
@@ -976,7 +986,7 @@ std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t
if ( CCaddress_balance(coinaddr) == 0 )
{
CCerror = strprintf("M.%d N.%d but pubkeys[%d] has no balance",M,N,i);
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
}
@@ -988,43 +998,43 @@ std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t
if ( _GetCCaddress(destaddr,EVAL_GATEWAYS,gatewayspk) == 0 )
{
CCerror = strprintf("Gateway bind.%s (%s) cant create globaladdr",coin.c_str(),uint256_str(str,tokenid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( (fullsupply=CCfullsupply(tokenid)) != totalsupply )
{
CCerror = strprintf("Gateway bind.%s (%s) globaladdr.%s totalsupply %.8f != fullsupply %.8f",coin.c_str(),uint256_str(str,tokenid),cp->unspendableCCaddr,(double)totalsupply/COIN,(double)fullsupply/COIN);
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( CCtoken_balance(myTokenCCaddr,tokenid) != totalsupply )
{
CCerror = strprintf("token balance on %s %.8f != %.8f",myTokenCCaddr,(double)CCtoken_balance(myTokenCCaddr,tokenid)/COIN,(double)totalsupply/COIN);
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( GetTransaction(oracletxid,oracletx,hashBlock,false) == 0 || (numvouts= oracletx.vout.size()) <= 0 )
{
CCerror = strprintf("cant find oracletxid %s",uint256_str(str,oracletxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( DecodeOraclesCreateOpRet(oracletx.vout[numvouts-1].scriptPubKey,name,description,format) != 'C' )
{
CCerror = strprintf("mismatched oracle name %s != %s",name.c_str(),coin.c_str());
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( (fstr=(char *)format.c_str()) == 0 || strncmp(fstr,"Ihh",3) != 0 )
{
CCerror = strprintf("illegal format (%s) != (%s)",fstr,(char *)"Ihh");
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( GatewaysBindExists(cp,gatewayspk,tokenid) != 0 )
{
CCerror = strprintf("Gateway bind.%s (%s) already exists",coin.c_str(),uint256_str(str,tokenid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( AddNormalinputs(mtx,mypk,2*txfee,3) > 0 )
@@ -1037,7 +1047,7 @@ std::string GatewaysBind(uint64_t txfee,std::string coin,uint256 tokenid,int64_t
}
}
CCerror = strprintf("cant find enough inputs");
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
@@ -1052,30 +1062,31 @@ std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
LogPrint("gatewayscc-1","GatewaysDeposit ht.%d %s %.8f numpks.%d\n",height,refcoin.c_str(),(double)amount/COIN,(int32_t)pubkeys.size());
LOGSTREAM("gatewayscc",CCLOG_DEBUG1, stream << "GatewaysDeposit ht." << height << " " << refcoin << " " << (double)amount/COIN << " numpks." << (int32_t)pubkeys.size() << std::endl);
if ( GetTransaction(bindtxid,bindtx,hashBlock,false) == 0 || (numvouts= bindtx.vout.size()) <= 0 )
{
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( DecodeGatewaysBindOpRet(depositaddr,bindtx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B' || refcoin != coin )
{
CCerror = strprintf("invalid coin - bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if (komodo_txnotarizedconfirmed(bindtxid)==false)
{
CCerror = strprintf("gatewaysbind tx not yet confirmed/notarized");
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
n = (int32_t)pubkeys.size();
merkleroot = zeroid;
for (i=m=0; i<n; i++)
{
LogPrint("gatewayscc","pubkeys[%d] %s\n",i,pubkey33_str(str,(uint8_t *)&pubkeys[i]));
pubkey33_str(str,(uint8_t *)&pubkeys[i]);
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << "pubkeys[" << i << "] " << str << std::endl);
if ( (mhash= GatewaysReverseScan(txid,height,oracletxid,OraclesBatontxid(oracletxid,pubkeys[i]))) != zeroid )
{
if ( merkleroot == zeroid )
@@ -1086,23 +1097,23 @@ std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::
txids.push_back(txid);
}
}
LogPrint("gatewayscc","cointxid.%s m.%d of n.%d\n",uint256_str(str,cointxid),m,n);
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << "cointxid." << cointxid.GetHex() << " m." << m << " of n." << n << std::endl);
if ( merkleroot == zeroid || m < n/2 )
{
CCerror = strprintf("couldnt find merkleroot for ht.%d %s oracle.%s m.%d vs n.%d",height,coin.c_str(),uint256_str(str,oracletxid),m,n);
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( GatewaysCointxidExists(cp,cointxid) != 0 )
{
CCerror = strprintf("cointxid.%s already exists",uint256_str(str,cointxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( GatewaysVerify(depositaddr,oracletxid,claimvout,coin,cointxid,deposithex,proof,merkleroot,destpub,taddr,prefix,prefix2) != amount )
{
CCerror = strprintf("deposittxid didnt validate");
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( AddNormalinputs(mtx,mypk,3*txfee,4) > 0 )
@@ -1112,7 +1123,7 @@ std::string GatewaysDeposit(uint64_t txfee,uint256 bindtxid,int32_t height,std::
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysDepositOpRet('D',bindtxid,coin,publishers,txids,height,cointxid,claimvout,deposithex,proof,destpub,amount)));
}
CCerror = strprintf("cant find enough inputs");
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
@@ -1132,49 +1143,49 @@ std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,ui
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
{
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2,wiftype) != 'B' || coin != refcoin )
{
CCerror = strprintf("invalid coin - bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if (komodo_txnotarizedconfirmed(bindtxid)==false)
{
CCerror = strprintf("gatewaysbind tx not yet confirmed/notarized");
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( GetTransaction(deposittxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
{
CCerror = strprintf("cant find deposittxid %s",uint256_str(str,bindtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if (DecodeGatewaysDepositOpRet(tx.vout[numvouts-1].scriptPubKey,tmptxid,coin,publishers,txids,height,cointxid,claimvout,deposithex,proof,tmpdestpub,tmpamount) != 'D' || coin != refcoin)
{
CCerror = strprintf("invalid coin - deposittxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if (komodo_txnotarizedconfirmed(deposittxid)==false)
{
CCerror = strprintf("gatewaysdeposit tx not yet confirmed/notarized");
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if (tmpdestpub!=destpub)
{
CCerror = strprintf("different destination pubkey from desdeposit tx");
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( (depositamount=GatewaysDepositval(tx,mypk)) != amount )
{
CCerror = strprintf("invalid Gateways deposittxid %s %.8f != %.8f",uint256_str(str,deposittxid),(double)depositamount/COIN,(double)amount/COIN);
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( AddNormalinputs(mtx,mypk,txfee,3) > 0 )
@@ -1189,7 +1200,7 @@ std::string GatewaysClaim(uint64_t txfee,uint256 bindtxid,std::string refcoin,ui
}
}
CCerror = strprintf("cant find enough inputs or mismatched total");
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
@@ -1211,19 +1222,19 @@ std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin
if( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
{
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2,wiftype) != 'B' || coin != refcoin )
{
CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if (komodo_txnotarizedconfirmed(bindtxid)==false)
{
CCerror = strprintf("gatewaysbind tx not yet confirmed/notarized");
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
_GetCCaddress(coinaddr,EVAL_GATEWAYS,gatewayspk);
@@ -1241,7 +1252,7 @@ std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin
&& refcoin==coin && tmptokenid==tokenid && tmpbindtxid==bindtxid)
{
CCerror = strprintf("unable to create withdraw, another withdraw pending");
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
@@ -1250,7 +1261,7 @@ std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin
&& refcoin==coin && tmptokenid==tokenid && tmpbindtxid==bindtxid)
{
CCerror = strprintf("unable to create withdraw, another withdraw pending");
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
}
@@ -1268,12 +1279,12 @@ std::string GatewaysWithdraw(uint64_t txfee,uint256 bindtxid,std::string refcoin
else
{
CCerror = strprintf("not enough balance of tokens for withdraw");
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
}
CCerror = strprintf("cant find enough normal inputs");
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
@@ -1294,7 +1305,7 @@ std::string GatewaysPartialSign(uint64_t txfee,uint256 lasttxid,std::string refc
|| (funcid=DecodeGatewaysOpRet(tx.vout[numvouts-1].scriptPubKey))==0 || (funcid!='W' && funcid!='P'))
{
CCerror = strprintf("can't find last tx %s",uint256_str(str,lasttxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if (funcid=='W')
@@ -1303,26 +1314,26 @@ std::string GatewaysPartialSign(uint64_t txfee,uint256 lasttxid,std::string refc
if (DecodeGatewaysWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,tmptokenid,bindtxid,coin,withdrawpub,amount)!='W' || refcoin!=coin)
{
CCerror = strprintf("invalid withdraw tx %s",uint256_str(str,lasttxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (komodo_txnotarizedconfirmed(withdrawtxid)==false)
{
CCerror = strprintf("gatewayswithdraw tx not yet confirmed/notarized");
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (GetTransaction(bindtxid,tmptx,hashBlock,false)==0 || (numvouts=tmptx.vout.size())<=0)
{
CCerror = strprintf("can't find bind tx %s",uint256_str(str,bindtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (DecodeGatewaysBindOpRet(depositaddr,tmptx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B'
|| refcoin!=coin || tokenid!=tmptokenid)
{
CCerror = strprintf("invalid bind tx %s",uint256_str(str,bindtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
}
@@ -1331,39 +1342,39 @@ std::string GatewaysPartialSign(uint64_t txfee,uint256 lasttxid,std::string refc
if (DecodeGatewaysPartialOpRet(tx.vout[numvouts-1].scriptPubKey,withdrawtxid,coin,K,signerpk,tmphex)!='P' || refcoin!=coin)
{
CCerror = strprintf("cannot decode partialsign tx opret %s",uint256_str(str,lasttxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (GetTransaction(withdrawtxid,tmptx,hashBlock,false)==0 || (numvouts= tmptx.vout.size())<=0)
{
CCerror = strprintf("can't find withdraw tx %s",uint256_str(str,withdrawtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (DecodeGatewaysWithdrawOpRet(tmptx.vout[numvouts-1].scriptPubKey,tmptokenid,bindtxid,coin,withdrawpub,amount)!='W'
|| refcoin!=coin)
{
CCerror = strprintf("invalid withdraw tx %s",uint256_str(str,lasttxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (komodo_txnotarizedconfirmed(withdrawtxid)==false)
{
CCerror = strprintf("gatewayswithdraw tx not yet confirmed/notarized");
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (GetTransaction(bindtxid,tmptx,hashBlock,false)==0 || (numvouts=tmptx.vout.size())<=0)
{
CCerror = strprintf("can't find bind tx %s",uint256_str(str,bindtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (DecodeGatewaysBindOpRet(depositaddr,tmptx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B'
|| refcoin!=coin || tokenid!=tmptokenid)
{
CCerror = strprintf("invalid bind tx %s",uint256_str(str,bindtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
}
@@ -1374,7 +1385,7 @@ std::string GatewaysPartialSign(uint64_t txfee,uint256 lasttxid,std::string refc
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysPartialOpRet('P',withdrawtxid,refcoin,K+1,mypk,hex)));
}
CCerror = strprintf("error adding funds for partialsign");
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
@@ -1394,7 +1405,7 @@ std::string GatewaysCompleteSigning(uint64_t txfee,uint256 lasttxid,std::string
|| (funcid=DecodeGatewaysOpRet(tx.vout[numvouts-1].scriptPubKey))==0 || (funcid!='W' && funcid!='P'))
{
CCerror = strprintf("invalid last txid %s",uint256_str(str,lasttxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if (funcid=='W')
@@ -1403,26 +1414,26 @@ std::string GatewaysCompleteSigning(uint64_t txfee,uint256 lasttxid,std::string
if (DecodeGatewaysWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,tmptokenid,bindtxid,coin,withdrawpub,amount)!='W' || refcoin!=coin)
{
CCerror = strprintf("cannot decode withdraw tx opret %s",uint256_str(str,lasttxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (GetTransaction(bindtxid,tmptx,hashBlock,false)==0 || (numvouts=tmptx.vout.size())<=0)
{
CCerror = strprintf("can't find bind tx %s",uint256_str(str,bindtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (komodo_txnotarizedconfirmed(withdrawtxid)==false)
{
CCerror = strprintf("gatewayswithdraw tx not yet confirmed/notarized");
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (DecodeGatewaysBindOpRet(depositaddr,tmptx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B'
|| refcoin!=coin || tokenid!=tmptokenid)
{
CCerror = strprintf("invalid bind tx %s",uint256_str(str,bindtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
}
@@ -1431,38 +1442,38 @@ std::string GatewaysCompleteSigning(uint64_t txfee,uint256 lasttxid,std::string
if (DecodeGatewaysPartialOpRet(tx.vout[numvouts-1].scriptPubKey,withdrawtxid,coin,K,signerpk,tmphex)!='P' || refcoin!=coin)
{
CCerror = strprintf("cannot decode partialsign tx opret %s",uint256_str(str,lasttxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (GetTransaction(withdrawtxid,tmptx,hashBlock,false)==0 || (numvouts=tmptx.vout.size())==0)
{
CCerror = strprintf("invalid withdraw txid %s",uint256_str(str,withdrawtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (DecodeGatewaysWithdrawOpRet(tmptx.vout[numvouts-1].scriptPubKey,tmptokenid,bindtxid,coin,withdrawpub,amount)!='W' || refcoin!=coin)
{
CCerror = strprintf("cannot decode withdraw tx opret %s",uint256_str(str,withdrawtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (komodo_txnotarizedconfirmed(withdrawtxid)==false)
{
CCerror = strprintf("gatewayswithdraw tx not yet confirmed/notarized");
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (GetTransaction(bindtxid,tmptx,hashBlock,false)==0 || (numvouts=tmptx.vout.size())<=0)
{
CCerror = strprintf("can't find bind tx %s",uint256_str(str,bindtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (DecodeGatewaysBindOpRet(depositaddr,tmptx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B'
|| refcoin!=coin || tokenid!=tmptokenid)
{
CCerror = strprintf("invalid bind tx %s",uint256_str(str,bindtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
}
@@ -1473,7 +1484,7 @@ std::string GatewaysCompleteSigning(uint64_t txfee,uint256 lasttxid,std::string
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysCompleteSigningOpRet('S',withdrawtxid,refcoin,K+1,hex)));
}
CCerror = strprintf("error adding funds for completesigning");
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
@@ -1491,44 +1502,44 @@ std::string GatewaysMarkDone(uint64_t txfee,uint256 completetxid,std::string ref
if (GetTransaction(completetxid,tx,hashBlock,false)==0 || (numvouts= tx.vout.size())<=0)
{
CCerror = strprintf("invalid completesigning txid %s",uint256_str(str,completetxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (DecodeGatewaysCompleteSigningOpRet(tx.vout[numvouts-1].scriptPubKey,withdrawtxid,coin,K,hex)!='S' || refcoin!=coin)
{
CCerror = strprintf("cannot decode completesigning tx opret %s",uint256_str(str,completetxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if (komodo_txnotarizedconfirmed(completetxid)==false)
{
CCerror = strprintf("gatewayscompletesigning tx not yet confirmed/notarized");
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (GetTransaction(withdrawtxid,tx,hashBlock,false)==0 || (numvouts= tx.vout.size())==0)
{
CCerror = strprintf("invalid withdraw txid %s",uint256_str(str,withdrawtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (DecodeGatewaysWithdrawOpRet(tx.vout[numvouts-1].scriptPubKey,tmptokenid,bindtxid,coin,withdrawpub,amount)!='W' || refcoin!=coin)
{
CCerror = strprintf("cannot decode withdraw tx opret %s\n",uint256_str(str,withdrawtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (GetTransaction(bindtxid,tx,hashBlock,false)==0 || (numvouts=tx.vout.size())<=0)
{
CCerror = strprintf("can't find bind tx %s",uint256_str(str,bindtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
else if (DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B'
|| refcoin!=coin || tokenid!=tmptokenid)
{
CCerror = strprintf("invalid bind tx %s",uint256_str(str,bindtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if (AddNormalinputs(mtx,mypk,txfee,3)!=0)
@@ -1538,7 +1549,7 @@ std::string GatewaysMarkDone(uint64_t txfee,uint256 completetxid,std::string ref
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,EncodeGatewaysMarkDoneOpRet('M',withdrawtxid,refcoin,completetxid)));
}
CCerror = strprintf("error adding funds for markdone");
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
@@ -1558,13 +1569,13 @@ UniValue GatewaysPendingDeposits(uint256 bindtxid,std::string refcoin)
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
{
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,pubkeys,taddr,prefix,prefix2,wiftype) != 'B' || refcoin != coin)
{
CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
SetCCunspents(unspentOutputs,coinaddr);
@@ -1613,13 +1624,13 @@ UniValue GatewaysPendingWithdraws(uint256 bindtxid,std::string refcoin)
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
{
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2,wiftype) != 'B' || refcoin != coin )
{
CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
n = msigpubkeys.size();
@@ -1701,13 +1712,13 @@ UniValue GatewaysProcessedWithdraws(uint256 bindtxid,std::string refcoin)
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
{
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2,wiftype) != 'B' || refcoin != coin)
{
CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
n = msigpubkeys.size();
@@ -1779,13 +1790,13 @@ UniValue GatewaysExternalAddress(uint256 bindtxid,CPubKey pubkey)
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
{
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2,wiftype) != 'B')
{
CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
GetCustomscriptaddress(addr,CScript() << ParseHex(HexStr(pubkey)) << OP_CHECKSIG,taddr,prefix,prefix2);
@@ -1803,19 +1814,19 @@ UniValue GatewaysDumpPrivKey(uint256 bindtxid,CKey key)
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
{
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2,wiftype) != 'B')
{
CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
priv=EncodeCustomSecret(key,wiftype);
result.push_back(Pair("result","success"));
result.push_back(Pair("address",priv.c_str()));
result.push_back(Pair("privkey",priv.c_str()));
return(result);
}
@@ -1832,13 +1843,13 @@ UniValue GatewaysInfo(uint256 bindtxid)
if ( GetTransaction(bindtxid,tx,hashBlock,false) == 0 || (numvouts= tx.vout.size()) <= 0 )
{
CCerror = strprintf("cant find bindtxid %s",uint256_str(str,bindtxid));
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( DecodeGatewaysBindOpRet(depositaddr,tx.vout[numvouts-1].scriptPubKey,tokenid,coin,totalsupply,oracletxid,M,N,msigpubkeys,taddr,prefix,prefix2,wiftype) != 'B')
{
CCerror = strprintf("invalid bindtxid %s coin.%s",uint256_str(str,bindtxid),coin.c_str());
LogPrint("gatewayscc","%s\n", CCerror.c_str() );
LOGSTREAM("gatewayscc",CCLOG_INFO, stream << CCerror << std::endl);
return("");
}
if ( GetTransaction(bindtxid,tx,hashBlock,false) != 0 )

View File

@@ -255,25 +255,25 @@ template <class Helper> int64_t IsHeirFundingVout(struct CCcontract_info* cp, co
}
// makes coin initial tx opret
CScript EncodeHeirCreateOpRet(uint8_t funcid, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName, std::string memo)
vscript_t EncodeHeirCreateOpRet(uint8_t funcid, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName, std::string memo)
{
uint8_t evalcode = EVAL_HEIR;
return CScript() << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << ownerPubkey << heirPubkey << inactivityTimeSec << heirName << memo);
return /*CScript() << OP_RETURN <<*/ E_MARSHAL(ss << evalcode << funcid << ownerPubkey << heirPubkey << inactivityTimeSec << heirName << memo);
}
// makes coin additional tx opret
CScript EncodeHeirOpRet(uint8_t funcid, uint256 fundingtxid, uint8_t hasHeirSpendingBegun)
vscript_t EncodeHeirOpRet(uint8_t funcid, uint256 fundingtxid, uint8_t hasHeirSpendingBegun)
{
uint8_t evalcode = EVAL_HEIR;
fundingtxid = revuint256(fundingtxid);
return CScript() << OP_RETURN << E_MARSHAL(ss << evalcode << funcid << fundingtxid << hasHeirSpendingBegun);
return /*CScript() << OP_RETURN <<*/ E_MARSHAL(ss << evalcode << funcid << fundingtxid << hasHeirSpendingBegun);
}
// decode opret vout for Heir contract
uint8_t _DecodeHeirOpRet(std::vector<uint8_t> vopret, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, std::string& memo, uint256& fundingTxidInOpret, uint8_t &hasHeirSpendingBegun, bool noLogging)
uint8_t _DecodeHeirOpRet(vscript_t vopret, CPubKey& ownerPubkey, CPubKey& heirPubkey, int64_t& inactivityTime, std::string& heirName, std::string& memo, uint256& fundingTxidInOpret, uint8_t &hasHeirSpendingBegun, bool noLogging)
{
uint8_t evalCodeInOpret = 0;
uint8_t heirFuncId = 0;
@@ -287,13 +287,13 @@ uint8_t _DecodeHeirOpRet(std::vector<uint8_t> vopret, CPubKey& ownerPubkey, CPub
uint8_t heirFuncId = 0;
hasHeirSpendingBegun = 0;
bool result = E_UNMARSHAL(vopret, { ss >> evalCodeInOpret; ss >> heirFuncId; \
if (heirFuncId == 'F') { \
ss >> ownerPubkey; ss >> heirPubkey; ss >> inactivityTime; ss >> heirName; ss >> memo; \
} \
else { \
ss >> fundingTxidInOpret >> hasHeirSpendingBegun; \
} \
bool result = E_UNMARSHAL(vopret, { ss >> evalCodeInOpret; ss >> heirFuncId;
if (heirFuncId == 'F') {
ss >> ownerPubkey; ss >> heirPubkey; ss >> inactivityTime; ss >> heirName; ss >> memo;
}
else {
ss >> fundingTxidInOpret >> hasHeirSpendingBegun;
}
});
if (!result) {
@@ -327,9 +327,11 @@ uint8_t _DecodeHeirEitherOpRet(CScript scriptPubKey, uint256 &tokenid, CPubKey&
{
uint8_t evalCodeTokens = 0;
std::vector<CPubKey> voutPubkeysDummy;
std::vector<uint8_t> vopretExtra /*, vopretStripped*/;
std::vector<std::pair<uint8_t, vscript_t>> oprets;
vscript_t vopretExtra /*, vopretStripped*/;
if (DecodeTokenOpRet(scriptPubKey, evalCodeTokens, tokenid, voutPubkeysDummy, vopretExtra) != 0) {
if (DecodeTokenOpRet(scriptPubKey, evalCodeTokens, tokenid, voutPubkeysDummy, oprets) != 0 && GetOpretBlob(oprets, OPRETID_HEIRDATA, vopretExtra)) {
/* if (vopretExtra.size() > 1) {
// restore the second opret:

View File

@@ -7,8 +7,8 @@
#define IS_CHARINSTR(c, str) (std::string(str).find((char)(c)) != std::string::npos)
// makes coin initial tx opret
CScript EncodeHeirCreateOpRet(uint8_t funcid, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName, std::string memo);
CScript EncodeHeirOpRet(uint8_t funcid, uint256 fundingtxid, uint8_t isHeirSpendingBegan);
vscript_t EncodeHeirCreateOpRet(uint8_t funcid, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName, std::string memo);
vscript_t EncodeHeirOpRet(uint8_t funcid, uint256 fundingtxid, uint8_t isHeirSpendingBegan);
uint256 FindLatestFundingTx(uint256 fundingtxid, uint256 &tokenid, CScript& opRetScript, uint8_t &isHeirSpendingBegan);
//uint8_t DecodeHeirOpRet(CScript scriptPubKey, uint256& fundingtxid, uint8_t &isHeirSpendingBegan, bool noLogging = false);
@@ -29,13 +29,13 @@ public:
}
static CScript makeCreateOpRet(uint256 dummyid, std::vector<CPubKey> dummyPubkeys, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName, std::string memo) {
return EncodeHeirCreateOpRet((uint8_t)'F', ownerPubkey, heirPubkey, inactivityTimeSec, heirName, memo);
return CScript() << OP_RETURN << EncodeHeirCreateOpRet((uint8_t)'F', ownerPubkey, heirPubkey, inactivityTimeSec, heirName, memo);
}
static CScript makeAddOpRet(uint256 dummyid, std::vector<CPubKey> dummyPubkeys, uint256 fundingtxid, uint8_t isHeirSpendingBegan) {
return EncodeHeirOpRet((uint8_t)'A', fundingtxid, isHeirSpendingBegan);
return CScript() << OP_RETURN << EncodeHeirOpRet((uint8_t)'A', fundingtxid, isHeirSpendingBegan);
}
static CScript makeClaimOpRet(uint256 dummyid, std::vector<CPubKey> dummyPubkeys, uint256 fundingtxid, uint8_t isHeirSpendingBegan) {
return EncodeHeirOpRet((uint8_t)'C', fundingtxid, isHeirSpendingBegan);
return CScript() << OP_RETURN << EncodeHeirOpRet((uint8_t)'C', fundingtxid, isHeirSpendingBegan);
}
static CTxOut make1of2Vout(int64_t amount, CPubKey ownerPubkey, CPubKey heirPubkey) {
return MakeCC1of2vout(EVAL_HEIR, amount, ownerPubkey, heirPubkey);
@@ -71,15 +71,15 @@ public:
static CScript makeCreateOpRet(uint256 tokenid, std::vector<CPubKey> voutTokenPubkeys, CPubKey ownerPubkey, CPubKey heirPubkey, int64_t inactivityTimeSec, std::string heirName, std::string memo) {
return EncodeTokenOpRet(tokenid, voutTokenPubkeys,
EncodeHeirCreateOpRet((uint8_t)'F', ownerPubkey, heirPubkey, inactivityTimeSec, heirName, memo));
std::make_pair(OPRETID_HEIRDATA, EncodeHeirCreateOpRet((uint8_t)'F', ownerPubkey, heirPubkey, inactivityTimeSec, heirName, memo)));
}
static CScript makeAddOpRet(uint256 tokenid, std::vector<CPubKey> voutTokenPubkeys, uint256 fundingtxid, uint8_t isHeirSpendingBegan) {
return EncodeTokenOpRet(tokenid, voutTokenPubkeys,
EncodeHeirOpRet((uint8_t)'A', fundingtxid, isHeirSpendingBegan));
std::make_pair(OPRETID_HEIRDATA, EncodeHeirOpRet((uint8_t)'A', fundingtxid, isHeirSpendingBegan)));
}
static CScript makeClaimOpRet(uint256 tokenid, std::vector<CPubKey> voutTokenPubkeys, uint256 fundingtxid, uint8_t isHeirSpendingBegan) {
return EncodeTokenOpRet(tokenid, voutTokenPubkeys,
EncodeHeirOpRet((uint8_t)'C', fundingtxid, isHeirSpendingBegan));
std::make_pair(OPRETID_HEIRDATA, EncodeHeirOpRet((uint8_t)'C', fundingtxid, isHeirSpendingBegan)));
}
static CTxOut make1of2Vout(int64_t amount, CPubKey ownerPubkey, CPubKey heirPubkey) {

View File

@@ -478,5 +478,3 @@ bool Eval::ImportCoin(const std::vector<uint8_t> params,const CTransaction &impo
}
return Valid();
}

7
src/cc/makecustom Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/sh
gcc -O3 -DBUILD_CUSTOMCC -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c -o customcc.so cclib.cpp
cp customcc.so ../libcc.so
cd ..
make
cd cc

View File

@@ -1,15 +1,14 @@
#!/bin/sh
cd rogue;
make clean;
if [ "$HOST" = "x86_64-w64-mingw32" ]; then
echo building rogue.exe...
./configure --host=x86_64-w64-mingw32
mkdir ncurses && cd ncurses
echo $PWD
wget https://invisible-island.net/datafiles/release/mingw32.zip
unzip mingw32.zip && rm mingw32.zip
wget https://github.com/KomodoPlatform/rogue/releases/download/0.3.3b-01/x86_64-w64-mingw32.tar.gz
tar xvfz x86_64-w64-mingw32.tar.gz && rm x86_64-w64-mingw32.tar.gz
echo lib archive cleaned
cd ..
echo $PWD
if make -f Makefile_win "$@"; then
echo rogue.exe build SUCCESSFUL

2
src/cc/maketetris Executable file
View File

@@ -0,0 +1,2 @@
gcc -O3 -std=c++11 -I../secp256k1/include -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -DSTANDALONE tetris.cpp -lncurses -o tetris

View File

@@ -167,7 +167,7 @@ int32_t MarmaraGetbatontxid(std::vector<uint256> &creditloop,uint256 &batontxid,
creditloop.push_back(txid);
//fprintf(stderr,"%d: %s\n",n,txid.GetHex().c_str());
n++;
if ( (value= CCgettxout(spenttxid,vout,1)) == 10000 )
if ( (value= CCgettxout(spenttxid,vout,1,1)) == 10000 )
{
batontxid = spenttxid;
//fprintf(stderr,"got baton %s %.8f\n",batontxid.GetHex().c_str(),(double)value/COIN);
@@ -388,7 +388,11 @@ int64_t AddMarmarainputs(CMutableTransaction &mtx,std::vector<CPubKey> &pubkeys,
uint64_t threshold,nValue,totalinputs = 0; uint256 txid,hashBlock; CTransaction tx; int32_t numvouts,ht,unlockht,vout,i,n = 0; uint8_t funcid; CPubKey pk; std::vector<int64_t> vals;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
SetCCunspents(unspentOutputs,coinaddr);
threshold = total/(maxinputs+1);
if ( maxinputs > CC_MAXVINS )
maxinputs = CC_MAXVINS;
if ( maxinputs > 0 )
threshold = total/maxinputs;
else threshold = total;
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
txid = it->first.txhash;

View File

@@ -15,203 +15,675 @@
#include "CCPayments.h"
/*
Payments CC is a catchall CC, supported invoices, zpayments, automated funds allocation, including token based revshare
/*
0) txidopret <- allocation, scriptPubKey, opret
1) create <- locked_blocks, minrelease, list of txidopret
2) fund createtxid amount opretflag to global CC address with opret or txidaddr without
3) release amount -> vout[i] will be scriptPubKeys[i] and (amount * allocations[i]) / sumallocations[] (only using vins that have been locked for locked_blocks+).
4) info txid -> display parameters, funds
5) list -> all txids
First step is to create txids with the info needed in their opreturns. this info is the weight, scriptPubKey and opret if needed. To do that txidopret is used:
./c is a script that invokes komodo-cli with the correct -ac_name
./c paymentstxidopret \"[9,%222102d6f13a8f745921cdb811e32237bb98950af1a5952be7b3d429abd9152f8e388dac%22]\" -> rawhex with txid 95d9fc8d8a3ef63693c7427e59ff5e177ef63b7345d5f6d6497ac262699a8def
./c paymentstxidopret \"[1,%2221039433dc3749aece1bd568f374a45da3b0bc6856990d7da3cd175399577940a775ac%22]\" -> rawhex txid 00469695a08b975ceaf7258896abbf1455eb0f383e8a98fc650deace4cbf02a1
now we have 2 txid with the required info in the opreturn. one of them has a 9 and the other a 1 for a 90%/10% split.
./c paymentscreate \"[0,0,%2295d9fc8d8a3ef63693c7427e59ff5e177ef63b7345d5f6d6497ac262699a8def%22,%2200469695a08b975ceaf7258896abbf1455eb0f383e8a98fc650deace4cbf02a1%22]\" -> created txid 318d827cc6d8f25f40517e7fb0982e3f707b4aa749d322483fc336686a87b28a that will be the createtxid that the other rpc calls will use.
lets see if this appears in the list
./c paymentslist ->
{
"result": "success",
"createtxids": [
"318d827cc6d8f25f40517e7fb0982e3f707b4aa749d322483fc336686a87b28a"
]
}
It appeared! now lets get more info on it:
./c paymentsinfo \"[%22318d827cc6d8f25f40517e7fb0982e3f707b4aa749d322483fc336686a87b28a%22]\"
{
"lockedblocks": 0,
"totalallocations": 10,
"minrelease": 0,
"RWRM36sC8jSctyFZtsu7CyDcHYPdZX7nPZ": 0.00000000,
"REpyKi7avsVduqZ3eimncK4uKqSArLTGGK": 0.00000000,
"totalfunds": 0.00000000,
"result": "success"
}
There are 2 possible places the funds for this createtxid can be, the first is the special address that is derived from combining the globalCC address with the txidaddr. txidaddr is a non-spendable markeraddress created by converting the txid into a 33 byte pubkey by prefixing 0x02 to the txid. It is a 1of2 address, so it doesnt matter that nobody knows the privkey for this txidaddr. the second address is the global CC address and only utxo to that address with an opreturn containing the createtxid are funds valid for this payments CC createtxid
next let us add some funds to it. the funds can be to either of the two addresses, controlled by useopret (defaults to 0)
./c paymentsfund \"[%22318d827cc6d8f25f40517e7fb0982e3f707b4aa749d322483fc336686a87b28a%22,1,0]\" -> txid 28f69b925bb7a21d2a3ba2327e85eb2031b014e976e43f5c2c6fb8a76767b221, which indeed sent funds to RWRM36sC8jSctyFZtsu7CyDcHYPdZX7nPZ without an opreturn and it appears on the payments info.
./c paymentsfund \"[%22318d827cc6d8f25f40517e7fb0982e3f707b4aa749d322483fc336686a87b28a%22,1,1]\" -> txid cc93330b5c951b724b246b3b138d00519c33f2a600a7c938bc9e51aff6e20e32, which indeed sent funds to REpyKi7avsVduqZ3eimncK4uKqSArLTGGK with an opreturn and it appears on the payments info.
./c paymentsrelease \"[%22318d827cc6d8f25f40517e7fb0982e3f707b4aa749d322483fc336686a87b28a%22,1.5]\" -> a8d5dbbb8ee94c05e75c4f3c5221091f59dcb86e0e9c4e1e3d2cf69e6fce6b81
it used both fund utxos
*/
// start of consensus code
int64_t IsPaymentsvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v)
CScript EncodePaymentsTxidOpRet(int32_t allocation,std::vector<uint8_t> scriptPubKey,std::vector<uint8_t> destopret)
{
CScript opret; uint8_t evalcode = EVAL_PAYMENTS;
opret << OP_RETURN << E_MARSHAL(ss << evalcode << 'T' << allocation << scriptPubKey << destopret);
return(opret);
}
uint8_t DecodePaymentsTxidOpRet(CScript scriptPubKey,int32_t &allocation,std::vector<uint8_t> &destscriptPubKey,std::vector<uint8_t> &destopret)
{
std::vector<uint8_t> vopret; uint8_t *script,e,f;
GetOpReturnData(scriptPubKey, vopret);
script = (uint8_t *)vopret.data();
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> allocation; ss >> destscriptPubKey; ss >> destopret) != 0 )
{
if ( e == EVAL_PAYMENTS && f == 'T' )
return(f);
}
return(0);
}
CScript EncodePaymentsFundOpRet(uint256 checktxid)
{
CScript opret; uint8_t evalcode = EVAL_PAYMENTS;
opret << OP_RETURN << E_MARSHAL(ss << evalcode << 'F' << checktxid);
return(opret);
}
uint8_t DecodePaymentsFundOpRet(CScript scriptPubKey,uint256 &checktxid)
{
std::vector<uint8_t> vopret; uint8_t *script,e,f;
GetOpReturnData(scriptPubKey, vopret);
script = (uint8_t *)vopret.data();
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> checktxid) != 0 )
{
if ( e == EVAL_PAYMENTS && f == 'F' )
return(f);
}
return(0);
}
CScript EncodePaymentsOpRet(int32_t lockedblocks,int32_t minrelease,int32_t totalallocations,std::vector<uint256> txidoprets)
{
CScript opret; uint8_t evalcode = EVAL_PAYMENTS;
opret << OP_RETURN << E_MARSHAL(ss << evalcode << 'C' << lockedblocks << minrelease << totalallocations << txidoprets);
return(opret);
}
uint8_t DecodePaymentsOpRet(CScript scriptPubKey,int32_t &lockedblocks,int32_t &minrelease,int32_t &totalallocations,std::vector<uint256> &txidoprets)
{
std::vector<uint8_t> vopret; uint8_t *script,e,f;
GetOpReturnData(scriptPubKey, vopret);
script = (uint8_t *)vopret.data();
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> lockedblocks; ss >> minrelease; ss >> totalallocations; ss >> txidoprets) != 0 )
{
if ( e == EVAL_PAYMENTS && f == 'C' )
return(f);
}
return(0);
}
int64_t IsPaymentsvout(struct CCcontract_info *cp,const CTransaction& tx,int32_t v,char *cmpaddr)
{
char destaddr[64];
if ( tx.vout[v].scriptPubKey.IsPayToCryptoCondition() != 0 )
{
if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && strcmp(destaddr,cp->unspendableCCaddr) == 0 )
if ( Getscriptaddress(destaddr,tx.vout[v].scriptPubKey) > 0 && (cmpaddr[0] == 0 || strcmp(destaddr,cmpaddr) == 0) )
return(tx.vout[v].nValue);
}
return(0);
}
bool PaymentsExactAmounts(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx,int32_t minage,uint64_t txfee)
{
static uint256 zerohash;
CTransaction vinTx; uint256 hashBlock,activehash; int32_t i,numvins,numvouts; int64_t inputs=0,outputs=0,assetoshis;
numvins = tx.vin.size();
numvouts = tx.vout.size();
for (i=0; i<numvins; i++)
{
//fprintf(stderr,"vini.%d\n",i);
if ( (*cp->ismyvin)(tx.vin[i].scriptSig) != 0 )
{
//fprintf(stderr,"vini.%d check mempool\n",i);
if ( eval->GetTxUnconfirmed(tx.vin[i].prevout.hash,vinTx,hashBlock) == 0 )
return eval->Invalid("cant find vinTx");
else
{
//fprintf(stderr,"vini.%d check hash and vout\n",i);
if ( hashBlock == zerohash )
return eval->Invalid("cant Payments from mempool");
if ( (assetoshis= IsPaymentsvout(cp,vinTx,tx.vin[i].prevout.n)) != 0 )
inputs += assetoshis;
}
}
}
for (i=0; i<numvouts; i++)
{
//fprintf(stderr,"i.%d of numvouts.%d\n",i,numvouts);
if ( (assetoshis= IsPaymentsvout(cp,tx,i)) != 0 )
outputs += assetoshis;
}
if ( inputs != outputs+txfee )
{
fprintf(stderr,"inputs %llu vs outputs %llu\n",(long long)inputs,(long long)outputs);
return eval->Invalid("mismatched inputs != outputs + txfee");
}
else return(true);
}
bool PaymentsValidate(struct CCcontract_info *cp,Eval* eval,const CTransaction &tx, uint32_t nIn)
{
int32_t numvins,numvouts,preventCCvins,preventCCvouts,i,numblocks; bool retval; uint256 txid; uint8_t hash[32]; char str[65],destaddr[64];
return eval->Invalid("no validation yet");
std::vector<std::pair<CAddressIndexKey, CAmount> > txids;
numvins = tx.vin.size();
numvouts = tx.vout.size();
preventCCvins = preventCCvouts = -1;
if ( numvouts < 1 )
return eval->Invalid("no vouts");
else
{
for (i=0; i<numvins; i++)
{
if ( IsCCInput(tx.vin[0].scriptSig) == 0 )
{
return eval->Invalid("illegal normal vini");
}
}
//fprintf(stderr,"check amounts\n");
if ( PaymentsExactAmounts(cp,eval,tx,1,10000) == false )
{
fprintf(stderr,"Paymentsget invalid amount\n");
return false;
}
else
{
txid = tx.GetHash();
memcpy(hash,&txid,sizeof(hash));
retval = PreventCC(eval,tx,preventCCvins,numvins,preventCCvouts,numvouts);
if ( retval != 0 )
fprintf(stderr,"Paymentsget validated\n");
else fprintf(stderr,"Paymentsget invalid\n");
return(retval);
}
}
// one of two addresses
// change must go to 1of2 txidaddr
// only 'F' or 1of2 txidaddr can be spent
// all vouts must match exactly
return(true);
}
// end of consensus code
// helper functions for rpc calls in rpcwallet.cpp
int64_t AddPaymentsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey pk,int64_t total,int32_t maxinputs)
int64_t AddPaymentsInputs(struct CCcontract_info *cp,CMutableTransaction &mtx,CPubKey txidpk,int64_t total,int32_t maxinputs,uint256 createtxid,int32_t latestheight)
{
// add threshold check
char coinaddr[64]; int64_t nValue,price,totalinputs = 0; uint256 txid,hashBlock; std::vector<uint8_t> origpubkey; CTransaction vintx; int32_t vout,n = 0;
char coinaddr[64]; CPubKey Paymentspk; int64_t nValue,threshold,price,totalinputs = 0; uint256 txid,checktxid,hashBlock; std::vector<uint8_t> origpubkey; CTransaction vintx,tx; int32_t iter,vout,ht,n = 0;
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
GetCCaddress(cp,coinaddr,pk);
SetCCunspents(unspentOutputs,coinaddr);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
if ( maxinputs > CC_MAXVINS )
maxinputs = CC_MAXVINS;
if ( maxinputs > 0 )
threshold = total/maxinputs;
else threshold = total;
Paymentspk = GetUnspendable(cp,0);
for (iter=0; iter<2; iter++)
{
txid = it->first.txhash;
vout = (int32_t)it->first.index;
// no need to prevent dup
if ( GetTransaction(txid,vintx,hashBlock,false) != 0 )
if ( iter == 0 )
GetCCaddress(cp,coinaddr,Paymentspk);
else GetCCaddress1of2(cp,coinaddr,Paymentspk,txidpk);
SetCCunspents(unspentOutputs,coinaddr);
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
if ( (nValue= IsPaymentsvout(cp,vintx,vout)) > 1000000 && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 )
txid = it->first.txhash;
vout = (int32_t)it->first.index;
//fprintf(stderr,"iter.%d %s/v%d %s\n",iter,txid.GetHex().c_str(),vout,coinaddr);
if ( vout == 0 && GetTransaction(txid,vintx,hashBlock,false) != 0 )
{
if ( total != 0 && maxinputs != 0 )
mtx.vin.push_back(CTxIn(txid,vout,CScript()));
nValue = it->second.satoshis;
totalinputs += nValue;
n++;
if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) )
break;
if ( latestheight != 0 )
{
if ( (ht= komodo_blockheight(hashBlock)) == 0 )
{
fprintf(stderr,"null ht\n");
continue;
}
else if ( ht > latestheight )
{
fprintf(stderr,"ht.%d > lastheight.%d\n",ht,latestheight);
continue;
}
}
if ( iter == 0 )
{
std::vector<uint8_t> scriptPubKey,opret;
if ( myGetTransaction(txid,tx,hashBlock) == 0 || tx.vout.size() < 2 || DecodePaymentsFundOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,checktxid) != 'F' || checktxid != createtxid )
{
fprintf(stderr,"bad opret %s vs %s\n",checktxid.GetHex().c_str(),createtxid.GetHex().c_str());
continue;
}
}
if ( (nValue= IsPaymentsvout(cp,vintx,vout,coinaddr)) > PAYMENTS_TXFEE && nValue >= threshold && myIsutxo_spentinmempool(ignoretxid,ignorevin,txid,vout) == 0 )
{
if ( total != 0 && maxinputs != 0 )
mtx.vin.push_back(CTxIn(txid,vout,CScript()));
nValue = it->second.satoshis;
totalinputs += nValue;
n++;
if ( (total > 0 && totalinputs >= total) || (maxinputs > 0 && n >= maxinputs) )
break;
} //else fprintf(stderr,"nValue %.8f vs threshold %.8f\n",(double)nValue/COIN,(double)threshold/COIN);
}
}
}
return(totalinputs);
}
std::string PaymentsGet(uint64_t txfee,int64_t nValue)
UniValue payments_rawtxresult(UniValue &result,std::string rawtx,int32_t broadcastflag)
{
CMutableTransaction tmpmtx,mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,Paymentspk; int64_t inputs,CCchange=0; struct CCcontract_info *cp,C; std::string rawhex; uint32_t j; int32_t i,len; uint8_t buf[32768]; bits256 hash;
cp = CCinit(&C,EVAL_PAYMENTS);
if ( txfee == 0 )
txfee = 10000;
Paymentspk = GetUnspendable(cp,0);
mypk = pubkey2pk(Mypubkey());
if ( (inputs= AddPaymentsInputs(cp,mtx,Paymentspk,nValue+txfee,60)) > 0 )
CTransaction tx;
if ( rawtx.size() > 0 )
{
if ( inputs > nValue )
CCchange = (inputs - nValue - txfee);
if ( CCchange != 0 )
mtx.vout.push_back(MakeCC1vout(EVAL_PAYMENTS,CCchange,Paymentspk));
mtx.vout.push_back(CTxOut(nValue,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
fprintf(stderr,"start at %u\n",(uint32_t)time(NULL));
j = rand() & 0xfffffff;
for (i=0; i<1000000; i++,j++)
result.push_back(Pair("hex",rawtx));
if ( DecodeHexTx(tx,rawtx) != 0 )
{
tmpmtx = mtx;
rawhex = FinalizeCCTx(-1LL,cp,tmpmtx,mypk,txfee,CScript() << OP_RETURN << E_MARSHAL(ss << (uint8_t)EVAL_PAYMENTS << (uint8_t)'G' << j));
if ( (len= (int32_t)rawhex.size()) > 0 && len < 65536 )
{
len >>= 1;
decode_hex(buf,len,(char *)rawhex.c_str());
hash = bits256_doublesha256(0,buf,len);
if ( (hash.bytes[0] & 0xff) == 0 && (hash.bytes[31] & 0xff) == 0 )
{
fprintf(stderr,"found valid txid after %d iterations %u\n",i,(uint32_t)time(NULL));
return(rawhex);
}
//fprintf(stderr,"%02x%02x ",hash.bytes[0],hash.bytes[31]);
}
}
fprintf(stderr,"couldnt generate valid txid %u\n",(uint32_t)time(NULL));
return("");
} else fprintf(stderr,"cant find Payments inputs\n");
return("");
}
std::string PaymentsFund(uint64_t txfee,int64_t funds)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey mypk,Paymentspk; CScript opret; struct CCcontract_info *cp,C;
cp = CCinit(&C,EVAL_PAYMENTS);
if ( txfee == 0 )
txfee = 10000;
mypk = pubkey2pk(Mypubkey());
Paymentspk = GetUnspendable(cp,0);
if ( AddNormalinputs(mtx,mypk,funds+txfee,64) > 0 )
{
mtx.vout.push_back(MakeCC1vout(EVAL_PAYMENTS,funds,Paymentspk));
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,opret));
}
return("");
}
UniValue PaymentsInfo()
{
UniValue result(UniValue::VOBJ); char numstr[64];
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
CPubKey Paymentspk; struct CCcontract_info *cp,C; int64_t funding;
result.push_back(Pair("result","success"));
result.push_back(Pair("name","Payments"));
cp = CCinit(&C,EVAL_PAYMENTS);
Paymentspk = GetUnspendable(cp,0);
funding = AddPaymentsInputs(cp,mtx,Paymentspk,0,0);
sprintf(numstr,"%.8f",(double)funding/COIN);
result.push_back(Pair("funding",numstr));
if ( broadcastflag != 0 && myAddtomempool(tx) != 0 )
RelayTransaction(tx);
result.push_back(Pair("txid",tx.GetHash().ToString()));
result.push_back(Pair("result","success"));
} else result.push_back(Pair("error","decode hex"));
} else result.push_back(Pair("error","couldnt finalize payments CCtx"));
return(result);
}
cJSON *payments_reparse(int32_t *nump,char *jsonstr)
{
cJSON *params; char *newstr; int32_t i,j;
*nump = 0;
if ( jsonstr != 0 )
{
if ( jsonstr[0] == '"' && jsonstr[strlen(jsonstr)-1] == '"' )
{
jsonstr[strlen(jsonstr)-1] = 0;
jsonstr++;
}
newstr = (char *)malloc(strlen(jsonstr)+1);
for (i=j=0; jsonstr[i]!=0; i++)
{
if ( jsonstr[i] == '%' && jsonstr[i+1] == '2' && jsonstr[i+2] == '2' )
{
newstr[j++] = '"';
i += 2;
}
else if ( jsonstr[i] == '\'' )
newstr[j++] = '"';
else newstr[j++] = jsonstr[i];
}
newstr[j] = 0;
params = cJSON_Parse(newstr);
if ( 0 && params != 0 )
printf("new.(%s) -> %s\n",newstr,jprint(params,0));
free(newstr);
*nump = cJSON_GetArraySize(params);
} else params = 0;
return(params);
}
uint256 payments_juint256(cJSON *obj)
{
uint256 tmp; bits256 t = jbits256(obj,0);
memcpy(&tmp,&t,sizeof(tmp));
return(revuint256(tmp));
}
int32_t payments_parsehexdata(std::vector<uint8_t> &hexdata,cJSON *item,int32_t len)
{
char *hexstr; int32_t val;
if ( (hexstr= jstr(item,0)) != 0 && ((val= is_hexstr(hexstr,0)) == len*2 || (val > 0 && len == 0)) )
{
val >>= 1;
hexdata.resize(val);
decode_hex(&hexdata[0],val,hexstr);
return(0);
} else return(-1);
}
UniValue PaymentsRelease(struct CCcontract_info *cp,char *jsonstr)
{
int32_t latestheight,nextheight = komodo_nextheight();
CMutableTransaction tmpmtx,mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(),nextheight); UniValue result(UniValue::VOBJ); uint256 createtxid,hashBlock;
CTransaction tx,txO; CPubKey mypk,txidpk,Paymentspk; int32_t i,n,numoprets=0,lockedblocks,minrelease,totalallocations,checkallocations=0,allocation; int64_t inputsum,amount,CCchange=0; CTxOut vout; CScript onlyopret; char txidaddr[64],destaddr[64]; std::vector<uint256> txidoprets; std::string rawtx;
cJSON *params = payments_reparse(&n,jsonstr);
mypk = pubkey2pk(Mypubkey());
Paymentspk = GetUnspendable(cp,0);
if ( params != 0 && n == 2 )
{
createtxid = payments_juint256(jitem(params,0));
amount = jdouble(jitem(params,1),0) * SATOSHIDEN + 0.0000000049;
if ( myGetTransaction(createtxid,tx,hashBlock) != 0 )
{
if ( tx.vout.size() > 0 && DecodePaymentsOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,totalallocations,txidoprets) != 0 )
{
if ( lockedblocks < 0 || minrelease < 0 || totalallocations <= 0 || txidoprets.size() < 2 )
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","negative parameter"));
return(result);
}
latestheight = (nextheight - lockedblocks - 1);
if ( amount < minrelease )
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","amount too smal"));
result.push_back(Pair("amount",ValueFromAmount(amount)));
result.push_back(Pair("minrelease",ValueFromAmount(minrelease)));
return(result);
}
for (i=0; i<txidoprets.size(); i++)
{
std::vector<uint8_t> scriptPubKey,opret;
vout.nValue = 0;
if ( myGetTransaction(txidoprets[i],txO,hashBlock) != 0 && txO.vout.size() > 1 && DecodePaymentsTxidOpRet(txO.vout[txO.vout.size()-1].scriptPubKey,allocation,scriptPubKey,opret) == 'T' )
{
vout.nValue = allocation;
vout.scriptPubKey.resize(scriptPubKey.size());
memcpy(&vout.scriptPubKey[0],&scriptPubKey[0],scriptPubKey.size());
checkallocations += allocation;
if ( opret.size() > 0 )
{
scriptPubKey.resize(opret.size());
memcpy(&onlyopret[0],&opret[0],opret.size());
numoprets++;
}
} else break;
mtx.vout.push_back(vout);
}
if ( i != txidoprets.size() )
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","invalid txidoprets[i]"));
result.push_back(Pair("txi",(int64_t)i));
if ( params != 0 )
free_json(params);
return(result);
}
else if ( checkallocations != totalallocations )
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","totalallocations mismatch"));
result.push_back(Pair("checkallocations",(int64_t)checkallocations));
result.push_back(Pair("totalallocations",(int64_t)totalallocations));
if ( params != 0 )
free_json(params);
return(result);
}
else if ( numoprets > 1 )
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","too many oprets"));
result.push_back(Pair("numoprets",(int64_t)numoprets));
if ( params != 0 )
free_json(params);
return(result);
}
for (i=0; i<txidoprets.size(); i++)
{
mtx.vout[i].nValue *= amount;
mtx.vout[i].nValue /= totalallocations;
}
txidpk = CCtxidaddr(txidaddr,createtxid);
if ( (inputsum= AddPaymentsInputs(cp,mtx,txidpk,amount+PAYMENTS_TXFEE,60,createtxid,latestheight)) >= amount )
{
if ( (CCchange= (inputsum - amount)) >= PAYMENTS_TXFEE )
mtx.vout.push_back(MakeCC1of2vout(EVAL_PAYMENTS,CCchange,Paymentspk,txidpk));
GetCCaddress1of2(cp,destaddr,Paymentspk,txidpk);
CCaddr1of2set(cp,Paymentspk,txidpk,cp->CCpriv,destaddr);
rawtx = FinalizeCCTx(0,cp,mtx,mypk,PAYMENTS_TXFEE,onlyopret);
if ( params != 0 )
free_json(params);
return(payments_rawtxresult(result,rawtx,0));
}
else
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","couldnt find enough locked funds"));
}
}
else
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","couldnt decode paymentscreate txid opret"));
}
}
else
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","couldnt find paymentscreate txid"));
}
}
else
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","parameters error"));
}
if ( params != 0 )
free_json(params);
return(result);
}
UniValue PaymentsFund(struct CCcontract_info *cp,char *jsonstr)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); UniValue result(UniValue::VOBJ);
CPubKey Paymentspk,mypk,txidpk; uint256 txid,hashBlock; int64_t amount; CScript opret; CTransaction tx; char txidaddr[64]; std::string rawtx; int32_t n,useopret = 0,lockedblocks,minrelease,totalallocations; std::vector<uint256> txidoprets;
cJSON *params = payments_reparse(&n,jsonstr);
mypk = pubkey2pk(Mypubkey());
Paymentspk = GetUnspendable(cp,0);
if ( params != 0 && n > 1 && n <= 3 )
{
txid = payments_juint256(jitem(params,0));
amount = jdouble(jitem(params,1),0) * SATOSHIDEN + 0.0000000049;
if ( n == 3 )
useopret = jint(jitem(params,2),0) != 0;
if ( myGetTransaction(txid,tx,hashBlock) == 0 || tx.vout.size() == 1 || DecodePaymentsOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,totalallocations,txidoprets) == 0 )
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","invalid createtxid"));
}
else if ( AddNormalinputs(mtx,mypk,amount+PAYMENTS_TXFEE,60) > 0 )
{
if ( lockedblocks < 0 || minrelease < 0 || totalallocations <= 0 || txidoprets.size() < 2 )
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","negative parameter"));
if ( params != 0 )
free_json(params);
return(result);
}
if ( useopret == 0 )
{
txidpk = CCtxidaddr(txidaddr,txid);
mtx.vout.push_back(MakeCC1of2vout(EVAL_PAYMENTS,amount,Paymentspk,txidpk));
}
else
{
mtx.vout.push_back(MakeCC1vout(EVAL_PAYMENTS,amount,Paymentspk));
opret = EncodePaymentsFundOpRet(txid);
}
rawtx = FinalizeCCTx(0,cp,mtx,mypk,PAYMENTS_TXFEE,opret);
if ( params != 0 )
free_json(params);
return(payments_rawtxresult(result,rawtx,1));
}
else
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","couldnt find enough funds"));
}
}
else
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","parameters error"));
}
if ( params != 0 )
free_json(params);
return(result);
}
UniValue PaymentsTxidopret(struct CCcontract_info *cp,char *jsonstr)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight()); UniValue result(UniValue::VOBJ); CPubKey mypk; std::string rawtx;
std::vector<uint8_t> scriptPubKey,opret; int32_t allocation,n,retval0,retval1=0;
cJSON *params = payments_reparse(&n,jsonstr);
mypk = pubkey2pk(Mypubkey());
if ( params != 0 && n > 1 && n <= 3 )
{
allocation = juint(jitem(params,0),0);
retval0 = payments_parsehexdata(scriptPubKey,jitem(params,1),0);
if ( n == 3 )
retval1 = payments_parsehexdata(opret,jitem(params,2),0);
if ( allocation > 0 && retval0 == 0 && retval1 == 0 && AddNormalinputs(mtx,mypk,PAYMENTS_TXFEE,10) > 0 )
{
rawtx = FinalizeCCTx(0,cp,mtx,mypk,PAYMENTS_TXFEE,EncodePaymentsTxidOpRet(allocation,scriptPubKey,opret));
if ( params != 0 )
free_json(params);
return(payments_rawtxresult(result,rawtx,1));
}
result.push_back(Pair("result","error"));
result.push_back(Pair("error","invalid params or cant find txfee"));
}
else
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","parameters error"));
result.push_back(Pair("n",(int64_t)n));
fprintf(stderr,"(%s) %p\n",jsonstr,params);
}
if ( params != 0 )
free_json(params);
return(result);
}
UniValue PaymentsCreate(struct CCcontract_info *cp,char *jsonstr)
{
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
UniValue result(UniValue::VOBJ); CTransaction tx; CPubKey Paymentspk,mypk; char markeraddr[64]; std::vector<uint256> txidoprets; uint256 hashBlock; int32_t i,n,numoprets=0,lockedblocks,minrelease,totalallocations=0; std::string rawtx;
cJSON *params = payments_reparse(&n,jsonstr);
if ( params != 0 && n >= 4 )
{
lockedblocks = juint(jitem(params,0),0);
minrelease = juint(jitem(params,1),0);
if ( lockedblocks < 0 || minrelease < 0 )
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","negative parameter"));
if ( params != 0 )
free_json(params);
return(result);
}
for (i=0; i<n-2; i++)
txidoprets.push_back(payments_juint256(jitem(params,2+i)));
for (i=0; i<txidoprets.size(); i++)
{
std::vector<uint8_t> scriptPubKey,opret; int32_t allocation;
if ( myGetTransaction(txidoprets[i],tx,hashBlock) != 0 && tx.vout.size() > 1 && DecodePaymentsTxidOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,allocation,scriptPubKey,opret) == 'T' )
{
totalallocations += allocation;
if ( opret.size() > 0 )
numoprets++;
}
else
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","invalid txidopret"));
result.push_back(Pair("txid",txidoprets[i].GetHex()));
result.push_back(Pair("txi",(int64_t)i));
if ( params != 0 )
free_json(params);
return(result);
}
}
if ( numoprets > 1 )
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","too many opreturns"));
result.push_back(Pair("numoprets",(int64_t)numoprets));
if ( params != 0 )
free_json(params);
return(result);
}
mypk = pubkey2pk(Mypubkey());
Paymentspk = GetUnspendable(cp,0);
if ( AddNormalinputs(mtx,mypk,2*PAYMENTS_TXFEE,60) > 0 )
{
mtx.vout.push_back(MakeCC1of2vout(cp->evalcode,PAYMENTS_TXFEE,Paymentspk,Paymentspk));
rawtx = FinalizeCCTx(0,cp,mtx,mypk,PAYMENTS_TXFEE,EncodePaymentsOpRet(lockedblocks,minrelease,totalallocations,txidoprets));
if ( params != 0 )
free_json(params);
return(payments_rawtxresult(result,rawtx,1));
}
result.push_back(Pair("result","error"));
result.push_back(Pair("error","not enough normal funds"));
}
else
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","parameters error"));
}
if ( params != 0 )
free_json(params);
return(result);
}
UniValue PaymentsInfo(struct CCcontract_info *cp,char *jsonstr)
{
UniValue result(UniValue::VOBJ),a(UniValue::VARR); CTransaction tx,txO; CPubKey Paymentspk,txidpk; int32_t i,j,n,flag=0,allocation,numoprets=0,lockedblocks,minrelease,totalallocations; std::vector<uint256> txidoprets; int64_t funds,fundsopret; char fundsaddr[64],fundsopretaddr[64],txidaddr[64],*outstr; uint256 createtxid,hashBlock;
cJSON *params = payments_reparse(&n,jsonstr);
if ( params != 0 && n == 1 )
{
Paymentspk = GetUnspendable(cp,0);
createtxid = payments_juint256(jitem(params,0));
if ( myGetTransaction(createtxid,tx,hashBlock) != 0 )
{
if ( tx.vout.size() > 0 && DecodePaymentsOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,totalallocations,txidoprets) != 0 )
{
if ( lockedblocks < 0 || minrelease < 0 || totalallocations <= 0 || txidoprets.size() < 2 )
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","negative parameter"));
if ( params != 0 )
free_json(params);
return(result);
}
result.push_back(Pair("lockedblocks",(int64_t)lockedblocks));
result.push_back(Pair("totalallocations",(int64_t)totalallocations));
result.push_back(Pair("minrelease",(int64_t)minrelease));
for (i=0; i<txidoprets.size(); i++)
{
UniValue obj(UniValue::VOBJ); std::vector<uint8_t> scriptPubKey,opret;
obj.push_back(Pair("txidopret",txidoprets[i].GetHex()));
if ( myGetTransaction(txidoprets[i],txO,hashBlock) != 0 && txO.vout.size() > 1 && DecodePaymentsTxidOpRet(txO.vout[txO.vout.size()-1].scriptPubKey,allocation,scriptPubKey,opret) == 'T' )
{
outstr = (char *)malloc(scriptPubKey.size() + opret.size() + 1);
for (j=0; j<scriptPubKey.size(); j++)
outstr[j] = scriptPubKey[j];
outstr[j] = 0;
obj.push_back(Pair("scriptPubKey",outstr));
if ( opret.size() != 0 )
{
for (j=0; j<opret.size(); j++)
outstr[j] = opret[j];
outstr[j] = 0;
obj.push_back(Pair("opreturn",outstr));
numoprets++;
}
free(outstr);
}
}
flag++;
if ( numoprets > 1 )
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","too many opreturns"));
result.push_back(Pair("numoprets",(int64_t)numoprets));
}
else
{
txidpk = CCtxidaddr(txidaddr,createtxid);
GetCCaddress1of2(cp,fundsaddr,Paymentspk,txidpk);
funds = CCaddress_balance(fundsaddr);
result.push_back(Pair(fundsaddr,ValueFromAmount(funds)));
GetCCaddress(cp,fundsopretaddr,Paymentspk);
fundsopret = CCaddress_balance(fundsopretaddr);
result.push_back(Pair(fundsopretaddr,ValueFromAmount(fundsopret)));
result.push_back(Pair("totalfunds",ValueFromAmount(funds+fundsopret)));
result.push_back(Pair("result","success"));
}
}
}
if ( flag == 0 )
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","couldnt find valid payments create txid"));
}
}
else
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","parameters error"));
}
if ( params != 0 )
free_json(params);
return(result);
}
UniValue PaymentsList(struct CCcontract_info *cp,char *jsonstr)
{
std::vector<std::pair<CAddressIndexKey, CAmount> > addressIndex; uint256 txid,hashBlock;
UniValue result(UniValue::VOBJ),a(UniValue::VARR); char markeraddr[64],str[65]; CPubKey Paymentspk; CTransaction tx; int32_t lockedblocks,minrelease,totalallocations; std::vector<uint256> txidoprets;
Paymentspk = GetUnspendable(cp,0);
GetCCaddress1of2(cp,markeraddr,Paymentspk,Paymentspk);
SetCCtxids(addressIndex,markeraddr);
for (std::vector<std::pair<CAddressIndexKey, CAmount> >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++)
{
txid = it->first.txhash;
if ( it->first.index == 0 && myGetTransaction(txid,tx,hashBlock) != 0 )
{
if ( tx.vout.size() > 0 && DecodePaymentsOpRet(tx.vout[tx.vout.size()-1].scriptPubKey,lockedblocks,minrelease,totalallocations,txidoprets) == 'C' )
{
if ( lockedblocks < 0 || minrelease < 0 || totalallocations <= 0 || txidoprets.size() < 2 )
{
result.push_back(Pair("result","error"));
result.push_back(Pair("error","negative parameter"));
return(result);
}
a.push_back(uint256_str(str,txid));
}
}
}
result.push_back(Pair("result","success"));
result.push_back(Pair("createtxids",a));
return(result);
}

View File

@@ -334,7 +334,7 @@ std::string PricesAddFunding(uint64_t txfee,uint256 refbettoken,uint256 fundingt
std::vector<CPubKey> voutTokenPubkeysEmpty; //TODO: add token vout pubkeys
return(FinalizeCCTx(0,cp,mtx,mypk,txfee,
EncodeTokenOpRet(bettoken, voutTokenPubkeysEmpty,
EncodeAssetOpRet('t',/*bettoken,*/zeroid, 0, Mypubkey()))));
std::make_pair(OPRETID_ASSETSDATA, EncodeAssetOpRet('t',/*bettoken,*/zeroid, 0, Mypubkey())))));
}
else
{

View File

@@ -333,7 +333,11 @@ int64_t AddRewardsInputs(CScript &scriptPubKey,uint64_t maxseconds,struct CCcont
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
GetCCaddress(cp,coinaddr,pk);
SetCCunspents(unspentOutputs,coinaddr);
threshold = total/(maxinputs+1);
if ( maxinputs > CC_MAXVINS )
maxinputs = CC_MAXVINS;
if ( maxinputs > 0 )
threshold = total/maxinputs;
else threshold = total;
for (std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> >::const_iterator it=unspentOutputs.begin(); it!=unspentOutputs.end(); it++)
{
txid = it->first.txhash;

View File

@@ -26,10 +26,10 @@ O=o
CC = x86_64-w64-mingw32-gcc
#CFLAGS=-O2
CFLAGS= -g -O2 -I./ncurses/include -I./ncurses/include/ncursesw -I../../../depends/x86_64-w64-mingw32/include
CFLAGS= -g -O2 -I./x86_64-w64-mingw32/include -I./x86_64-w64-mingw32/include/ncursesw
#LIBS=-lcurses
LIBS = -L./ncurses/lib -lncursesw -lcurl
LIBS = -L./x86_64-w64-mingw32/lib -lncursesw -lcurl
#RM=rm -f
RM = rm -f

View File

@@ -25,7 +25,6 @@ command(struct rogue_state *rs)
char *fp;
THING *mp;
static char countch, direction, newcount = FALSE;
if (on(player, ISHASTE))
ntimes++;
/*
@@ -345,7 +344,7 @@ over:
if (wizard)
{
wizard = FALSE;
turn_see(TRUE);
turn_see(rs,TRUE);
msg(rs,"not wizard any more");
}
else
@@ -354,7 +353,7 @@ over:
if (wizard)
{
noscore = TRUE;
turn_see(FALSE);
turn_see(rs,FALSE);
msg(rs,"you are suddenly as smart as Ken Arnold in dungeon #%d", dnum);
}
else
@@ -404,7 +403,7 @@ over:
when CTRL('T'): teleport();
when CTRL('E'): msg(rs,"food left: %d", food_left);
when CTRL('C'): add_pass();
when CTRL('X'): turn_see(on(player, SEEMONST));
when CTRL('X'): turn_see(rs,on(player, SEEMONST));
when CTRL('~'):
{
THING *item;
@@ -456,7 +455,7 @@ over:
if (!running)
door_stop = FALSE;
}
/*
/*
* If he ran into something to take, let him pick it up.
*/
if (take != 0)

View File

@@ -160,10 +160,43 @@ extinguish(void (*func)(struct rogue_state *rs,int))
* do_fuses:
* Decrement counters and start needed fuses
*/
/*char *actionfunc_str(char *str,void *ptr)
{
if ( ptr == (void *)runners )
strcpy(str,"runners");
else if ( ptr == (void *)doctor )
strcpy(str,"doctor");
else if ( ptr == (void *)stomach )
strcpy(str,"stomach");
else if ( ptr == (void *)nohaste )
strcpy(str,"nohaste");
else if ( ptr == (void *)unconfuse )
strcpy(str,"unconfuse");
else if ( ptr == (void *)swander )
strcpy(str,"swander");
else if ( ptr == (void *)come_down )
strcpy(str,"come_down");
else if ( ptr == (void *)unsee )
strcpy(str,"unsee");
else if ( ptr == (void *)sight )
strcpy(str,"sight");
else if ( ptr == (void *)land )
strcpy(str,"land");
else if ( ptr == (void *)rollwand )
strcpy(str,"rollwand");
else if ( ptr == (void *)visuals )
strcpy(str,"visuals");
else if ( ptr == (void *)turn_see )
strcpy(str,"turn_see");
else strcpy(str,"no match");
return(str);
}*/
void
do_fuses(struct rogue_state *rs,int flag)
{
register struct delayed_action *wire;
register struct delayed_action *wire; char str[64];
/*
* Step though the list
@@ -175,6 +208,8 @@ do_fuses(struct rogue_state *rs,int flag)
*/
if (flag == wire->d_type && wire->d_time > 0 && --wire->d_time == 0)
{
//if ( fp != 0 )
// fprintf(fp,"t.%d %d %s, ",wire->d_type,wire->d_time,actionfunc_str(str,wire->d_func));
wire->d_type = EMPTY;
(*wire->d_func)(rs,wire->d_arg);
}

View File

@@ -21,6 +21,8 @@ void
doctor(struct rogue_state *rs,int arg)
{
register int lv, ohp;
if ( rs->logfp != 0 )
fprintf(rs->logfp,"doctor\n");
lv = pstats.s_lvl;
ohp = pstats.s_hpt;
@@ -52,6 +54,8 @@ doctor(struct rogue_state *rs,int arg)
void
swander(struct rogue_state *rs,int arg)
{
if ( rs->logfp != 0 )
fprintf(rs->logfp,"swander\n");
start_daemon(rollwand, 0, BEFORE);
}
@@ -63,6 +67,8 @@ int between = 0;
void
rollwand(struct rogue_state *rs,int arg)
{
if ( rs->logfp != 0 )
fprintf(rs->logfp,"rollwand\n");
if (++between >= 4)
{
if (roll(1, 6) == 4)
@@ -82,6 +88,8 @@ rollwand(struct rogue_state *rs,int arg)
void
unconfuse(struct rogue_state *rs,int arg)
{
if ( rs->logfp != 0 )
fprintf(rs->logfp,"unconfuse\n");
player.t_flags &= ~ISHUH;
msg(rs,"you feel less %s now", choose_str("trippy", "confused"));
}
@@ -94,6 +102,8 @@ void
unsee(struct rogue_state *rs,int arg)
{
register THING *th;
if ( rs->logfp != 0 )
fprintf(rs->logfp,"unsee\n");
for (th = mlist; th != NULL; th = next(th))
if (on(*th, ISINVIS) && see_monst(th))
@@ -108,6 +118,8 @@ unsee(struct rogue_state *rs,int arg)
void
sight(struct rogue_state *rs,int arg)
{
if ( rs->logfp != 0 )
fprintf(rs->logfp,"sight\n");
if (on(player, ISBLIND))
{
extinguish(sight);
@@ -126,6 +138,8 @@ sight(struct rogue_state *rs,int arg)
void
nohaste(struct rogue_state *rs,int arg)
{
if ( rs->logfp != 0 )
fprintf(rs->logfp,"nohaste\n");
player.t_flags &= ~ISHASTE;
msg(rs,"you feel yourself slowing down");
}
@@ -139,6 +153,8 @@ stomach(struct rogue_state *rs,int arg)
{
register int oldfood;
int orig_hungry = hungry_state;
if ( rs->logfp != 0 )
fprintf(rs->logfp,"stomach\n");
if (food_left <= 0)
{
@@ -194,41 +210,43 @@ come_down(struct rogue_state *rs,int arg)
{
register THING *tp;
register bool seemonst;
if ( rs->logfp != 0 )
fprintf(rs->logfp,"come_down\n");
if (!on(player, ISHALU))
return;
return;
kill_daemon(visuals);
player.t_flags &= ~ISHALU;
if (on(player, ISBLIND))
return;
return;
/*
* undo the things
*/
for (tp = lvl_obj; tp != NULL; tp = next(tp))
if (cansee(rs,tp->o_pos.y, tp->o_pos.x))
mvaddch(tp->o_pos.y, tp->o_pos.x, tp->o_type);
if (cansee(rs,tp->o_pos.y, tp->o_pos.x))
mvaddch(tp->o_pos.y, tp->o_pos.x, tp->o_type);
/*
* undo the monsters
*/
seemonst = on(player, SEEMONST);
for (tp = mlist; tp != NULL; tp = next(tp))
{
move(tp->t_pos.y, tp->t_pos.x);
if (cansee(rs,tp->t_pos.y, tp->t_pos.x))
if (!on(*tp, ISINVIS) || on(player, CANSEE))
addch(tp->t_disguise);
else
addch(chat(tp->t_pos.y, tp->t_pos.x));
else if (seemonst)
{
standout();
addch(tp->t_type);
standend();
}
move(tp->t_pos.y, tp->t_pos.x);
if (cansee(rs,tp->t_pos.y, tp->t_pos.x))
if (!on(*tp, ISINVIS) || on(player, CANSEE))
addch(tp->t_disguise);
else
addch(chat(tp->t_pos.y, tp->t_pos.x));
else if (seemonst)
{
standout();
addch(tp->t_type);
standend();
}
}
msg(rs,"Everything looks SO boring now.");
}
@@ -242,42 +260,44 @@ visuals(struct rogue_state *rs,int arg)
{
register THING *tp;
register bool seemonst;
if (!after || (running && jump))
return;
return;
if ( rs->logfp != 0 )
fprintf(rs->logfp,"visuals\n");
/*
* change the things
*/
for (tp = lvl_obj; tp != NULL; tp = next(tp))
if (cansee(rs,tp->o_pos.y, tp->o_pos.x))
mvaddch(tp->o_pos.y, tp->o_pos.x, rnd_thing());
if (cansee(rs,tp->o_pos.y, tp->o_pos.x))
mvaddch(tp->o_pos.y, tp->o_pos.x, rnd_thing());
/*
* change the stairs
*/
if (!seenstairs && cansee(rs,stairs.y, stairs.x))
mvaddch(stairs.y, stairs.x, rnd_thing());
mvaddch(stairs.y, stairs.x, rnd_thing());
/*
* change the monsters
*/
seemonst = on(player, SEEMONST);
for (tp = mlist; tp != NULL; tp = next(tp))
{
move(tp->t_pos.y, tp->t_pos.x);
if (see_monst(tp))
{
if (tp->t_type == 'X' && tp->t_disguise != 'X')
addch(rnd_thing());
else
addch(rnd(26) + 'A');
}
else if (seemonst)
{
standout();
addch(rnd(26) + 'A');
standend();
}
move(tp->t_pos.y, tp->t_pos.x);
if (see_monst(tp))
{
if (tp->t_type == 'X' && tp->t_disguise != 'X')
addch(rnd_thing());
else
addch(rnd(26) + 'A');
}
else if (seemonst)
{
standout();
addch(rnd(26) + 'A');
standend();
}
}
}
@@ -288,7 +308,54 @@ visuals(struct rogue_state *rs,int arg)
void
land(struct rogue_state *rs,int arg)
{
if ( rs->logfp != 0 )
fprintf(rs->logfp,"land\n");
player.t_flags &= ~ISLEVIT;
msg(rs,choose_str("bummer! You've hit the ground",
"you float gently to the ground"));
}
/*
* turn_see:
* Put on or off seeing monsters on this level
*/
bool
turn_see(struct rogue_state *rs,bool turn_off)
{
THING *mp;
bool can_see, add_new;
if ( rs->logfp != 0 )
fprintf(rs->logfp,"turn_see\n");
add_new = FALSE;
for (mp = mlist; mp != NULL; mp = next(mp))
{
move(mp->t_pos.y, mp->t_pos.x);
can_see = see_monst(mp);
if (turn_off)
{
if (!can_see)
addch(mp->t_oldch);
}
else
{
if (!can_see)
standout();
if (!on(player, ISHALU))
addch(mp->t_type);
else
addch(rnd(26) + 'A');
if (!can_see)
{
standend();
add_new ^= 1;//add_new++;
}
}
}
if (turn_off)
player.t_flags &= ~SEEMONST;
else
player.t_flags |= SEEMONST;
return add_new;
}

View File

@@ -107,6 +107,12 @@
#include <stdlib.h>
#include <time.h>
#ifdef _WIN32
#ifdef _MSC_VER
#include <stdint.h>
#endif
#endif
#undef SIGTSTP
#define MAXSTR 1024 /* maximum length of strings */
@@ -142,7 +148,8 @@ void leave(int);
void my_exit(int st);
void playltchars(void);
void quit(int);
int32_t _quit();
int32_t _quit();
void resetltchars(void);
void set_order(int *order, int numthings);
void tstp(int ignored);

View File

@@ -290,27 +290,27 @@ attack(struct rogue_state *rs,THING *mp)
}
when 'N':
{
register THING *obj, *steal;
register int nobj;
/*
* Nymph's steal a magic item, look through the pack
* and pick out one we like.
*/
steal = NULL;
for (nobj = 0, obj = pack; obj != NULL; obj = next(obj))
if (obj != cur_armor && obj != cur_weapon
&& obj != cur_ring[LEFT] && obj != cur_ring[RIGHT]
&& is_magic(obj) && rnd(++nobj) == 0)
steal = obj;
if (steal != NULL)
{
remove_mon(rs,&mp->t_pos, moat(mp->t_pos.y, mp->t_pos.x), FALSE);
mp=NULL;
leave_pack(rs,steal, FALSE, FALSE);
msg(rs,"she stole %s!", inv_name(steal, TRUE));
discard(steal);
}
THING *obj, *steal; int nobj;
/*
* Nymph's steal a magic item, look through the pack
* and pick out one we like.
*/
steal = NULL;
for (nobj = 0, obj = pack; obj != NULL; obj = next(obj))
if (obj != cur_armor && obj != cur_weapon
&& obj != cur_ring[LEFT] && obj != cur_ring[RIGHT]
&& is_magic(obj) && rnd(++nobj) == 0)
steal = obj;
if (steal != NULL)
{
remove_mon(rs,&mp->t_pos, moat(mp->t_pos.y, mp->t_pos.x), FALSE);
mp=NULL;
leave_pack(rs,steal, FALSE, FALSE);
msg(rs,"she stole %s!", inv_name(steal, TRUE));
if ( steal->o_count <= 0 )
discard(steal);
}
}
otherwise:
break;
@@ -594,26 +594,24 @@ void
remove_mon(struct rogue_state *rs,coord *mp, THING *tp, bool waskill)
{
register THING *obj, *nexti;
for (obj = tp->t_pack; obj != NULL; obj = nexti)
{
nexti = next(obj);
obj->o_pos = tp->t_pos;
detach(tp->t_pack, obj);
if (waskill)
fall(rs,obj, FALSE);
else
discard(obj);
nexti = next(obj);
obj->o_pos = tp->t_pos;
detach(tp->t_pack, obj);
if (waskill)
fall(rs,obj, FALSE);
else discard(obj);
}
moat(mp->y, mp->x) = NULL;
mvaddch(mp->y, mp->x, tp->t_oldch);
detach(mlist, tp);
if (on(*tp, ISTARGET))
{
kamikaze = FALSE;
to_death = FALSE;
if (fight_flush)
flush_type();
kamikaze = FALSE;
to_death = FALSE;
if (fight_flush)
flush_type();
}
discard(tp);
}

View File

@@ -167,7 +167,7 @@ readchar(struct rogue_state *rs)
fp = fopen("log","wb");
if ( fp != 0 )
{
fprintf(fp,"%d: (%c) hp.%d\n",counter,c,pstats.s_hpt);
fprintf(fp,"%d: (%c) hp.%d num.%d gold.%d seed.%llu\n",counter,c,pstats.s_hpt,num_packitems(rs),purse,(long long)seed);
fflush(fp);
counter++;
}

View File

@@ -19,80 +19,38 @@
int total = 0; /* total dynamic memory bytes */
#endif
/*
* detach:
* takes an item out of whatever linked list it might be in
*/
void
_detach(THING **list, THING *item)
{
if (*list == item)
*list = next(item);
if (prev(item) != NULL)
item->l_prev->l_next = next(item);
if (next(item) != NULL)
item->l_next->l_prev = prev(item);
item->l_next = NULL;
item->l_prev = NULL;
}
/*
* _attach:
* add an item to the head of a list
*/
void
_attach(THING **list, THING *item)
{
if (*list != NULL)
{
item->l_next = *list;
(*list)->l_prev = item;
item->l_prev = NULL;
}
else
{
item->l_next = NULL;
item->l_prev = NULL;
}
*list = item;
}
/*
* _free_list:
* Throw the whole blamed thing away
*/
void
_free_list(THING **ptr)
{
THING *item;
while (*ptr != NULL)
{
item = *ptr;
*ptr = next(item);
discard(item);
}
}
/*
* discard:
* Free up an item
*/
//#define ENABLE_DEBUG
#define MAX_DEBUGPTRS 100000
int32_t itemcounter;
THING *thingptrs[100000];
THING *thingptrs[MAX_DEBUGPTRS];
int32_t numptrs;
int32_t thing_find(THING *item)
{
#ifdef ENABLE_DEBUG
int32_t i;
for (i=0; i<numptrs; i++)
if ( item == thingptrs[i] )
return(i);
return(-1);
#else
return(0);
#endif
}
void
discard(THING *item)
{
#ifdef MASTER
total--;
#endif
if ( 0 )
#ifdef ENABLE_DEBUG
{
int32_t i;
for (i=0; i<numptrs; i++)
@@ -103,6 +61,17 @@ discard(THING *item)
break;
}
}
THING *list = pack;
for (; list != NULL; list = next(list))
{
if ( list == item )
{
fprintf(stderr,"pack item discarded? (%s)\n",inv_name(list,FALSE));
sleep(3);
break;
}
}
#endif
itemcounter--;
free((char *) item);
}
@@ -121,6 +90,63 @@ void garbage_collect()
numptrs = 0;
}
/*
* detach:
* takes an item out of whatever linked list it might be in
*/
void
_detach(THING **list, THING *item)
{
if (*list == item)
*list = next(item);
if (prev(item) != NULL)
item->l_prev->l_next = next(item);
if (next(item) != NULL)
item->l_next->l_prev = prev(item);
item->l_next = NULL;
item->l_prev = NULL;
}
/*
* _attach:
* add an item to the head of a list
*/
void
_attach(THING **list, THING *item)
{
if (*list != NULL)
{
item->l_next = *list;
(*list)->l_prev = item;
item->l_prev = NULL;
}
else
{
item->l_next = NULL;
item->l_prev = NULL;
}
*list = item;
}
/*
* _free_list:
* Throw the whole blamed thing away
*/
void
_free_list(THING **ptr)
{
THING *item;
while (*ptr != NULL)
{
item = *ptr;
*ptr = next(item);
discard(item);
}
}
/*
* new_item
* Get a new item with a specified size
@@ -139,12 +165,14 @@ new_item(void)
#else
item = (THING *)calloc(1, sizeof *item);
#endif
if ( 0 )
#ifdef ENABLE_DEBUG
if ( numptrs < MAX_DEBUGPTRS )
{
thingptrs[numptrs++] = item;
if ( (++itemcounter % 100) == 0 )
fprintf(stderr,"itemcounter.%d\n",itemcounter);
}
#endif
item->l_next = NULL;
item->l_prev = NULL;
return item;

View File

@@ -38,6 +38,31 @@ union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uin
typedef union _bits256 bits256;
#endif
#ifdef _WIN32
#ifdef _MSC_VER
int gettimeofday(struct timeval * tp, struct timezone * tzp)
{
// Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's
static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL);
SYSTEMTIME system_time;
FILETIME file_time;
uint64_t time;
GetSystemTime(&system_time);
SystemTimeToFileTime(&system_time, &file_time);
time = ((uint64_t)file_time.dwLowDateTime);
time += ((uint64_t)file_time.dwHighDateTime) << 32;
tp->tv_sec = (long)((time - EPOCH) / 10000000L);
tp->tv_usec = (long)(system_time.wMilliseconds * 1000);
return 0;
}
#endif // _MSC_VER
#endif
double OS_milliseconds()
{
struct timeval tv; double millis;
@@ -235,6 +260,7 @@ int32_t safecopy(char *dest,char *src,long len)
#endif
int32_t rogue_replay(uint64_t seed,int32_t sleeptime);
char *rogue_keystrokesload(int32_t *numkeysp,uint64_t seed,int32_t counter);
int rogue(int argc, char **argv, char **envp);
void *OS_loadfile(char *fname,uint8_t **bufp,long *lenp,long *allocsizep)
@@ -391,6 +417,12 @@ char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char *
}
#endif
#ifdef _WIN32
#ifdef _MSC_VER
#define sleep(x) Sleep(1000*(x))
#endif
#endif
/************************************************************************
*
* perform the query
@@ -708,11 +740,103 @@ char *komodo_issuemethod(char *userpass,char *method,char *params,uint16_t port)
#include "rogue.h"
void rogue_progress(struct rogue_state *rs,uint64_t seed,char *keystrokes,int32_t num)
int32_t rogue_sendrawtransaction(char *rawtx)
{
char cmd[16384],hexstr[16384],params[32768],*retstr; int32_t i;
char *params,*retstr,*hexstr; cJSON *retjson,*resobj; int32_t retval = -1;
params = (char *)malloc(strlen(rawtx) + 16);
sprintf(params,"[\"%s\"]",rawtx);
if ( (retstr= komodo_issuemethod(USERPASS,"sendrawtransaction",params,ROGUE_PORT)) != 0 )
{
if ( 0 ) // causes 4th level crash
{
static FILE *fp;
if ( fp == 0 )
fp = fopen("rogue.sendlog","wb");
if ( fp != 0 )
{
fprintf(fp,"%s\n",retstr);
fflush(fp);
}
}
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (resobj= jobj(retjson,"result")) != 0 )
{
if ( (hexstr= jstr(resobj,0)) != 0 && is_hexstr(hexstr,64) == 64 )
retval = 0;
}
free_json(retjson);
}
/* log sendrawtx result in file */
/*
FILE *debug_file;
debug_file = fopen("tx_debug.log", "a");
fprintf(debug_file, "%s\n", retstr);
fflush(debug_file);
fclose(debug_file);
*/
free(retstr);
}
free(params);
return(retval);
}
void rogue_progress(struct rogue_state *rs,int32_t waitflag,uint64_t seed,char *keystrokes,int32_t num)
{
char cmd[16384],hexstr[16384],params[32768],*retstr,*rawtx,*pastkeys,*pastcmp,*keys; int32_t i,len,numpastkeys; cJSON *retjson,*resobj;
//fprintf(stderr,"rogue_progress num.%d\n",num);
if ( rs->guiflag != 0 && Gametxidstr[0] != 0 )
{
if ( rs->keystrokeshex != 0 )
{
if ( rogue_sendrawtransaction(rs->keystrokeshex) == 0 )
{
if ( waitflag == 0 )
return;
else if ( 0 )
{
while ( rogue_sendrawtransaction(rs->keystrokeshex) == 0 )
{
//fprintf(stderr,"pre-rebroadcast\n");
sleep(10);
}
}
}
free(rs->keystrokeshex), rs->keystrokeshex = 0;
}
if ( 0 && (pastkeys= rogue_keystrokesload(&numpastkeys,seed,1)) != 0 )
{
sprintf(params,"[\"extract\",\"17\",\"[%%22%s%%22]\"]",Gametxidstr);
if ( (retstr= komodo_issuemethod(USERPASS,"cclib",params,ROGUE_PORT)) != 0 )
{
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (resobj= jobj(retjson,"result")) != 0 && (keys= jstr(resobj,"keystrokes")) != 0 )
{
len = strlen(keys) / 2;
pastcmp = (char *)malloc(len + 1);
decode_hex(pastcmp,len,keys);
fprintf(stderr,"keystrokes.(%s) vs pastkeys\n",keys);
for (i=0; i<numpastkeys; i++)
fprintf(stderr,"%02x",pastkeys[i]);
fprintf(stderr,"\n");
if ( len != numpastkeys || memcmp(pastcmp,pastkeys,len) != 0 )
{
fprintf(stderr,"pastcmp[%d] != pastkeys[%d]?\n",len,numpastkeys);
}
free(pastcmp);
} else fprintf(stderr,"no keystrokes in (%s)\n",retstr);
free_json(retjson);
} else fprintf(stderr,"error parsing.(%s)\n",retstr);
fprintf(stderr,"extracted.(%s)\n",retstr);
free(retstr);
} else fprintf(stderr,"error extracting game\n");
free(pastkeys);
} // else fprintf(stderr,"no pastkeys\n");
for (i=0; i<num; i++)
sprintf(&hexstr[i<<1],"%02x",keystrokes[i]&0xff);
hexstr[i<<1] = 0;
@@ -736,9 +860,29 @@ void rogue_progress(struct rogue_state *rs,uint64_t seed,char *keystrokes,int32_
fprintf(fp,"%s\n",retstr);
fflush(fp);
}
if ( (retjson= cJSON_Parse(retstr)) != 0 )
{
if ( (resobj= jobj(retjson,"result")) != 0 && (rawtx= jstr(resobj,"hex")) != 0 )
{
if ( rs->keystrokeshex != 0 )
free(rs->keystrokeshex);
rs->keystrokeshex = (char *)malloc(strlen(rawtx)+1);
strcpy(rs->keystrokeshex,rawtx);
//fprintf(stderr,"set keystrokestx <- %s\n",rs->keystrokeshex);
}
free_json(retjson);
}
free(retstr);
}
sleep(1);
if ( 0 && waitflag != 0 && rs->keystrokeshex != 0 )
{
while ( rogue_sendrawtransaction(rs->keystrokeshex) == 0 )
{
//fprintf(stderr,"post-rebroadcast\n");
sleep(3);
}
free(rs->keystrokeshex), rs->keystrokeshex = 0;
}
}
}
}
@@ -797,9 +941,46 @@ int32_t rogue_setplayerdata(struct rogue_state *rs,char *gametxidstr)
return(retval);
}
#ifdef _WIN32
#ifdef _MSC_VER
__inline int msver(void) {
switch (_MSC_VER) {
case 1500: return 2008;
case 1600: return 2010;
case 1700: return 2012;
case 1800: return 2013;
case 1900: return 2015;
//case 1910: return 2017;
default: return (_MSC_VER / 100);
}
}
static inline bool is_x64(void) {
#if defined(__x86_64__) || defined(_WIN64) || defined(__aarch64__)
return 1;
#elif defined(__amd64__) || defined(__amd64) || defined(_M_X64) || defined(_M_IA64)
return 1;
#else
return 0;
#endif
}
#define BUILD_DATE __DATE__ " " __TIME__
#endif // _WIN32
#endif // _MSC_VER
int main(int argc, char **argv, char **envp)
{
uint64_t seed; FILE *fp = 0; int32_t i,j,c; char userpass[8192];
#ifdef _WIN32
#ifdef _MSC_VER
printf("*** rogue for Windows [ Build %s ] ***\n", BUILD_DATE);
const char* arch = is_x64() ? "64-bits" : "32-bits";
printf(" Built with VC++ %d (%ld) %s\n\n", msver(), _MSC_FULL_VER, arch);
#endif
#endif
for (i=j=0; argv[0][i]!=0&&j<sizeof(ASSETCHAINS_SYMBOL); i++)
{
c = argv[0][i];
@@ -811,13 +992,34 @@ int main(int argc, char **argv, char **envp)
ASSETCHAINS_SYMBOL[j++] = toupper(c);
}
ASSETCHAINS_SYMBOL[j++] = 0;
#ifdef _WIN32
#ifdef _MSC_VER
if (strncmp(ASSETCHAINS_SYMBOL, "ROGUE.EXE", sizeof(ASSETCHAINS_SYMBOL)) == 0 || strncmp(ASSETCHAINS_SYMBOL, "ROGUE54.EXE", sizeof(ASSETCHAINS_SYMBOL)) == 0) {
strcpy(ASSETCHAINS_SYMBOL, "ROGUE"); // accept ROGUE.conf, instead of ROGUE.EXE.conf or ROGUE54.EXE.conf if build with MSVC
}
#endif
#endif
ROGUE_PORT = komodo_userpass(userpass,ASSETCHAINS_SYMBOL);
if ( IPADDRESS[0] == 0 )
strcpy(IPADDRESS,"127.0.0.1");
printf("ASSETCHAINS_SYMBOL.(%s) port.%u (%s) IPADDRESS.%s \n",ASSETCHAINS_SYMBOL,ROGUE_PORT,USERPASS,IPADDRESS); sleep(1);
if ( argc == 2 && (fp=fopen(argv[1],"rb")) == 0 )
{
seed = atol(argv[1]);
#ifdef _WIN32
#ifdef _MSC_VER
seed = _strtoui64(argv[1], NULL, 10);
fprintf(stderr, "replay seed.str(%s) seed.uint64_t(%I64u)", argv[1], seed);
#else
fprintf(stderr, "replay seed.str(%s) seed.uint64_t(%llu)", argv[1], (long long)seed);
seed = atol(argv[1]); // windows, but not MSVC
#endif // _MSC_VER
#else
seed = atol(argv[1]); // non-windows
#endif // _WIN32
//fprintf(stderr,"replay %llu\n",(long long)seed);
return(rogue_replay(seed,10));
}

View File

@@ -404,18 +404,18 @@ add_haste(struct rogue_state *rs,bool potion)
{
if (on(player, ISHASTE))
{
no_command += rnd(8);
player.t_flags &= ~(ISRUN|ISHASTE);
extinguish(nohaste);
msg(rs,"you faint from exhaustion");
return FALSE;
no_command += rnd(8);
player.t_flags &= ~(ISRUN|ISHASTE);
extinguish(nohaste);
msg(rs,"you faint from exhaustion");
return FALSE;
}
else
{
player.t_flags |= ISHASTE;
if (potion)
fuse(nohaste, 0, rnd(4)+4, AFTER);
return TRUE;
player.t_flags |= ISHASTE;
if (potion)
fuse(nohaste, 0, rnd(4)+4, AFTER);
return TRUE;
}
}

View File

@@ -124,7 +124,7 @@ wanderer(struct rogue_state *rs)
tp = new_item();
do
{
find_floor((struct room *) NULL, &cp, FALSE, TRUE);
find_floor(rs,(struct room *) NULL, &cp, FALSE, TRUE);
} while (roomin(rs,&cp) == proom);
new_monster(rs,tp, randmonster(TRUE), &cp);
if (on(player, SEEMONST))

View File

@@ -26,7 +26,17 @@ new_level(struct rogue_state *rs)
PLACE *pp;
char *sp;
int i;
if ( 0 )
{
static FILE *fp;
if ( fp == 0 )
fp = fopen("debug","wb");
if ( fp != 0 )
{
fprintf(fp,"newlevel seed.%llu\n",(long long)seed);
fflush(fp);
}
}
player.t_flags &= ~ISHELD; /* unhold when you go down just in case */
if (level > max_level)
max_level = level;
@@ -74,7 +84,7 @@ new_level(struct rogue_state *rs)
*/
do
{
find_floor((struct room *) NULL, &stairs, FALSE, FALSE);
find_floor(rs,(struct room *) NULL, &stairs, FALSE, FALSE);
} while (chat(stairs.y, stairs.x) != FLOOR);
sp = &flat(stairs.y, stairs.x);
*sp &= ~F_REAL;
@@ -84,18 +94,18 @@ new_level(struct rogue_state *rs)
/*
* Place the staircase down.
*/
find_floor((struct room *) NULL, &stairs, FALSE, FALSE);
find_floor(rs,(struct room *) NULL, &stairs, FALSE, FALSE);
chat(stairs.y, stairs.x) = STAIRS;
seenstairs = FALSE;
for (tp = mlist; tp != NULL; tp = next(tp))
tp->t_room = roomin(rs,&tp->t_pos);
find_floor((struct room *) NULL, &hero, FALSE, TRUE);
find_floor(rs,(struct room *) NULL, &hero, FALSE, TRUE);
enter_room(rs,&hero);
mvaddch(hero.y, hero.x, PLAYER);
if (on(player, SEEMONST))
turn_see(FALSE);
turn_see(rs,FALSE);
if (on(player, ISHALU))
visuals(rs,0);
}
@@ -153,7 +163,7 @@ put_things(struct rogue_state *rs)
/*
* Put it somewhere
*/
find_floor((struct room *) NULL, &obj->o_pos, FALSE, FALSE);
find_floor(rs,(struct room *) NULL, &obj->o_pos, FALSE, FALSE);
chat(obj->o_pos.y, obj->o_pos.x) = (char) obj->o_type;
}
/*
@@ -173,7 +183,7 @@ put_things(struct rogue_state *rs)
/*
* Put it somewhere
*/
find_floor((struct room *) NULL, &obj->o_pos, FALSE, FALSE);
find_floor(rs,(struct room *) NULL, &obj->o_pos, FALSE, FALSE);
chat(obj->o_pos.y, obj->o_pos.x) = AMULET;
}
}
@@ -201,7 +211,7 @@ treas_room(struct rogue_state *rs)
num_monst = nm = rnd(spots) + MINTREAS;
while (nm--)
{
find_floor(rp, &mp, 2 * MAXTRIES, FALSE);
find_floor(rs,rp, &mp, 2 * MAXTRIES, FALSE);
//fprintf(stderr,"treas_room\n");
tp = new_thing(rs);
tp->o_pos = mp;
@@ -222,7 +232,7 @@ treas_room(struct rogue_state *rs)
while (nm--)
{
spots = 0;
if (find_floor(rp, &mp, MAXTRIES, TRUE))
if (find_floor(rs,rp, &mp, MAXTRIES, TRUE))
{
tp = new_item();
new_monster(rs,tp, randmonster(FALSE), &mp);

View File

@@ -163,6 +163,11 @@ int32_t num_packitems(struct rogue_state *rs)
int32_t type = 0,n = 0,total = 0;
for (; list != NULL; list = next(list))
{
if ( thing_find(list) < 0 )
{
fprintf(stderr,"num_packitems cant find %p\n",list);
return(-1);
}
if ( list->o_packch != 0 )
{
n++;
@@ -219,29 +224,29 @@ THING *
leave_pack(struct rogue_state *rs,THING *obj, bool newobj, bool all)
{
THING *nobj;
inpack--;
nobj = obj;
if (obj->o_count > 1 && !all)
{
last_pick = obj;
obj->o_count--;
if (obj->o_group)
inpack++;
if (newobj)
{
nobj = new_item();
*nobj = *obj;
next(nobj) = NULL;
prev(nobj) = NULL;
nobj->o_count = 1;
}
last_pick = obj;
obj->o_count--;
if (obj->o_group)
inpack++;
if (newobj)
{
nobj = new_item();
*nobj = *obj;
next(nobj) = NULL;
prev(nobj) = NULL;
nobj->o_count = 1;
}
}
else
{
last_pick = NULL;
pack_used[obj->o_packch - 'a'] = FALSE;
detach(pack, obj);
last_pick = NULL;
pack_used[obj->o_packch - 'a'] = FALSE;
detach(pack, obj);
}
return nobj;
}
@@ -422,6 +427,8 @@ get_item(struct rogue_state *rs,char *purpose, int type)
{
for (;;)
{
if ( rs->replaydone != 0 )
return(NULL);
if (!terse)
addmsg(rs,"which object do you want to ");
addmsg(rs,purpose);
@@ -464,7 +471,9 @@ get_item(struct rogue_state *rs,char *purpose, int type)
return NULL;
}
else
{
return obj;
}
}
}
return NULL;

View File

@@ -27,31 +27,31 @@ do_passages(struct rogue_state *rs)
int roomcount;
static struct rdes
{
bool conn[MAXROOMS]; /* possible to connect to room i? */
bool isconn[MAXROOMS]; /* connection been made to room i? */
bool ingraph; /* this room in graph already? */
bool conn[MAXROOMS]; /* possible to connect to room i? */
bool isconn[MAXROOMS]; /* connection been made to room i? */
bool ingraph; /* this room in graph already? */
} rdes[MAXROOMS] = {
{ { 0, 1, 0, 1, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 1, 0, 1, 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 1, 0, 0, 0, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 1, 0, 0, 0, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 1, 0, 1, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 0, 1, 0, 1, 0, 0, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 0, 0, 1, 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 0, 0, 0, 1, 0, 1, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 0, 0, 0, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 1, 0, 1, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 1, 0, 1, 0, 1, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 1, 0, 0, 0, 1, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 1, 0, 0, 0, 1, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 1, 0, 1, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 0, 1, 0, 1, 0, 0, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 0, 0, 1, 0, 0, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 0, 0, 0, 1, 0, 1, 0, 1 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
{ { 0, 0, 0, 0, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },
};
/*
* reinitialize room graph description
*/
for (r1 = rdes; r1 <= &rdes[MAXROOMS-1]; r1++)
{
for (j = 0; j < MAXROOMS; j++)
r1->isconn[j] = FALSE;
r1->ingraph = FALSE;
for (j = 0; j < MAXROOMS; j++)
r1->isconn[j] = FALSE;
r1->ingraph = FALSE;
}
/*
* starting with one room, connect it to a random adjacent room and
* then pick a new room to start with.
@@ -61,65 +61,65 @@ do_passages(struct rogue_state *rs)
r1->ingraph = TRUE;
do
{
/*
* find a room to connect with
*/
j = 0;
for (i = 0; i < MAXROOMS; i++)
if (r1->conn[i] && !rdes[i].ingraph && rnd(++j) == 0)
r2 = &rdes[i];
/*
* if no adjacent rooms are outside the graph, pick a new room
* to look from
*/
if (j == 0)
{
do
r1 = &rdes[rnd(MAXROOMS)];
until (r1->ingraph);
}
/*
* otherwise, connect new room to the graph, and draw a tunnel
* to it
*/
else
{
r2->ingraph = TRUE;
i = (int)(r1 - rdes);
j = (int)(r2 - rdes);
conn(rs,i, j);
r1->isconn[j] = TRUE;
r2->isconn[i] = TRUE;
roomcount++;
}
/*
* find a room to connect with
*/
j = 0;
for (i = 0; i < MAXROOMS; i++)
if (r1->conn[i] && !rdes[i].ingraph && rnd(++j) == 0)
r2 = &rdes[i];
/*
* if no adjacent rooms are outside the graph, pick a new room
* to look from
*/
if (j == 0)
{
do
r1 = &rdes[rnd(MAXROOMS)];
until (r1->ingraph);
}
/*
* otherwise, connect new room to the graph, and draw a tunnel
* to it
*/
else
{
r2->ingraph = TRUE;
i = (int)(r1 - rdes);
j = (int)(r2 - rdes);
conn(rs,i, j);
r1->isconn[j] = TRUE;
r2->isconn[i] = TRUE;
roomcount++;
}
} while (roomcount < MAXROOMS);
/*
* attempt to add passages to the graph a random number of times so
* that there isn't always just one unique passage through it.
*/
for (roomcount = rnd(5); roomcount > 0; roomcount--)
{
r1 = &rdes[rnd(MAXROOMS)]; /* a random room to look from */
/*
* find an adjacent room not already connected
*/
j = 0;
for (i = 0; i < MAXROOMS; i++)
if (r1->conn[i] && !r1->isconn[i] && rnd(++j) == 0)
r2 = &rdes[i];
/*
* if there is one, connect it and look for the next added
* passage
*/
if (j != 0)
{
i = (int)(r1 - rdes);
j = (int)(r2 - rdes);
conn(rs,i, j);
r1->isconn[j] = TRUE;
r2->isconn[i] = TRUE;
}
r1 = &rdes[rnd(MAXROOMS)]; /* a random room to look from */
/*
* find an adjacent room not already connected
*/
j = 0;
for (i = 0; i < MAXROOMS; i++)
if (r1->conn[i] && !r1->isconn[i] && rnd(++j) == 0)
r2 = &rdes[i];
/*
* if there is one, connect it and look for the next added
* passage
*/
if (j != 0)
{
i = (int)(r1 - rdes);
j = (int)(r2 - rdes);
conn(rs,i, j);
r1->isconn[j] = TRUE;
r2->isconn[i] = TRUE;
}
}
passnum();
}
@@ -138,22 +138,22 @@ conn(struct rogue_state *rs,int r1, int r2)
int rm;
char direc;
static coord del, curr, turn_delta, spos, epos;
if (r1 < r2)
{
rm = r1;
if (r1 + 1 == r2)
direc = 'r';
else
direc = 'd';
rm = r1;
if (r1 + 1 == r2)
direc = 'r';
else
direc = 'd';
}
else
{
rm = r2;
if (r2 + 1 == r1)
direc = 'r';
else
direc = 'd';
rm = r2;
if (r2 + 1 == r1)
direc = 'r';
else
direc = 'd';
}
rpf = &rooms[rm];
/*
@@ -162,75 +162,75 @@ conn(struct rogue_state *rs,int r1, int r2)
*/
if (direc == 'd')
{
rmt = rm + 3; /* room # of dest */
rpt = &rooms[rmt]; /* room pointer of dest */
del.x = 0; /* direction of move */
del.y = 1;
spos.x = rpf->r_pos.x; /* start of move */
spos.y = rpf->r_pos.y;
epos.x = rpt->r_pos.x; /* end of move */
epos.y = rpt->r_pos.y;
if (!(rpf->r_flags & ISGONE)) /* if not gone pick door pos */
do
{
spos.x = rpf->r_pos.x + rnd(rpf->r_max.x - 2) + 1;
spos.y = rpf->r_pos.y + rpf->r_max.y - 1;
} while ((rpf->r_flags&ISMAZE) && !(flat(spos.y, spos.x)&F_PASS));
if (!(rpt->r_flags & ISGONE))
do
{
epos.x = rpt->r_pos.x + rnd(rpt->r_max.x - 2) + 1;
} while ((rpt->r_flags&ISMAZE) && !(flat(epos.y, epos.x)&F_PASS));
distance = abs(spos.y - epos.y) - 1; /* distance to move */
turn_delta.y = 0; /* direction to turn */
turn_delta.x = (spos.x < epos.x ? 1 : -1);
turn_distance = abs(spos.x - epos.x); /* how far to turn */
rmt = rm + 3; /* room # of dest */
rpt = &rooms[rmt]; /* room pointer of dest */
del.x = 0; /* direction of move */
del.y = 1;
spos.x = rpf->r_pos.x; /* start of move */
spos.y = rpf->r_pos.y;
epos.x = rpt->r_pos.x; /* end of move */
epos.y = rpt->r_pos.y;
if (!(rpf->r_flags & ISGONE)) /* if not gone pick door pos */
do
{
spos.x = rpf->r_pos.x + rnd(rpf->r_max.x - 2) + 1;
spos.y = rpf->r_pos.y + rpf->r_max.y - 1;
} while ((rpf->r_flags&ISMAZE) && !(flat(spos.y, spos.x)&F_PASS));
if (!(rpt->r_flags & ISGONE))
do
{
epos.x = rpt->r_pos.x + rnd(rpt->r_max.x - 2) + 1;
} while ((rpt->r_flags&ISMAZE) && !(flat(epos.y, epos.x)&F_PASS));
distance = abs(spos.y - epos.y) - 1; /* distance to move */
turn_delta.y = 0; /* direction to turn */
turn_delta.x = (spos.x < epos.x ? 1 : -1);
turn_distance = abs(spos.x - epos.x); /* how far to turn */
}
else if (direc == 'r') /* setup for moving right */
{
rmt = rm + 1;
rpt = &rooms[rmt];
del.x = 1;
del.y = 0;
spos.x = rpf->r_pos.x;
spos.y = rpf->r_pos.y;
epos.x = rpt->r_pos.x;
epos.y = rpt->r_pos.y;
if (!(rpf->r_flags & ISGONE))
do
{
spos.x = rpf->r_pos.x + rpf->r_max.x - 1;
spos.y = rpf->r_pos.y + rnd(rpf->r_max.y - 2) + 1;
} while ((rpf->r_flags&ISMAZE) && !(flat(spos.y, spos.x)&F_PASS));
if (!(rpt->r_flags & ISGONE))
do
{
epos.y = rpt->r_pos.y + rnd(rpt->r_max.y - 2) + 1;
} while ((rpt->r_flags&ISMAZE) && !(flat(epos.y, epos.x)&F_PASS));
distance = abs(spos.x - epos.x) - 1;
turn_delta.y = (spos.y < epos.y ? 1 : -1);
turn_delta.x = 0;
turn_distance = abs(spos.y - epos.y);
rmt = rm + 1;
rpt = &rooms[rmt];
del.x = 1;
del.y = 0;
spos.x = rpf->r_pos.x;
spos.y = rpf->r_pos.y;
epos.x = rpt->r_pos.x;
epos.y = rpt->r_pos.y;
if (!(rpf->r_flags & ISGONE))
do
{
spos.x = rpf->r_pos.x + rpf->r_max.x - 1;
spos.y = rpf->r_pos.y + rnd(rpf->r_max.y - 2) + 1;
} while ((rpf->r_flags&ISMAZE) && !(flat(spos.y, spos.x)&F_PASS));
if (!(rpt->r_flags & ISGONE))
do
{
epos.y = rpt->r_pos.y + rnd(rpt->r_max.y - 2) + 1;
} while ((rpt->r_flags&ISMAZE) && !(flat(epos.y, epos.x)&F_PASS));
distance = abs(spos.x - epos.x) - 1;
turn_delta.y = (spos.y < epos.y ? 1 : -1);
turn_delta.x = 0;
turn_distance = abs(spos.y - epos.y);
}
#ifdef MASTER
else
debug("error in connection tables");
debug("error in connection tables");
#endif
turn_spot = rnd(distance - 1) + 1; /* where turn starts */
/*
* Draw in the doors on either side of the passage or just put #'s
* if the rooms are gone.
*/
if (!(rpf->r_flags & ISGONE))
door(rpf, &spos);
door(rpf, &spos);
else
putpass(&spos);
putpass(&spos);
if (!(rpt->r_flags & ISGONE))
door(rpt, &epos);
door(rpt, &epos);
else
putpass(&epos);
putpass(&epos);
/*
* Get ready to move...
*/
@@ -238,31 +238,31 @@ conn(struct rogue_state *rs,int r1, int r2)
curr.y = spos.y;
while (distance > 0)
{
/*
* Move to new position
*/
curr.x += del.x;
curr.y += del.y;
/*
* Check if we are at the turn place, if so do the turn
*/
if (distance == turn_spot)
while (turn_distance--)
{
putpass(&curr);
curr.x += turn_delta.x;
curr.y += turn_delta.y;
}
/*
* Continue digging along
*/
putpass(&curr);
distance--;
/*
* Move to new position
*/
curr.x += del.x;
curr.y += del.y;
/*
* Check if we are at the turn place, if so do the turn
*/
if (distance == turn_spot)
while (turn_distance--)
{
putpass(&curr);
curr.x += turn_delta.x;
curr.y += turn_delta.y;
}
/*
* Continue digging along
*/
putpass(&curr);
distance--;
}
curr.x += del.x;
curr.y += del.y;
if (!ce(curr, epos))
msg(rs,"warning, connectivity problem on this level");
msg(rs,"warning, connectivity problem on this level");
}
/*
@@ -274,13 +274,13 @@ void
putpass(coord *cp)
{
PLACE *pp;
pp = INDEX(cp->y, cp->x);
pp->p_flags |= F_PASS;
if (rnd(10) + 1 < level && rnd(40) == 0)
pp->p_flags &= ~F_REAL;
pp->p_flags &= ~F_REAL;
else
pp->p_ch = PASSAGE;
pp->p_ch = PASSAGE;
}
/*
@@ -293,23 +293,23 @@ void
door(struct room *rm, coord *cp)
{
PLACE *pp;
rm->r_exit[rm->r_nexits++] = *cp;
if (rm->r_flags & ISMAZE)
return;
return;
pp = INDEX(cp->y, cp->x);
if (rnd(10) + 1 < level && rnd(5) == 0)
{
if (cp->y == rm->r_pos.y || cp->y == rm->r_pos.y + rm->r_max.y - 1)
pp->p_ch = '-';
else
pp->p_ch = '|';
pp->p_flags &= ~F_REAL;
if (cp->y == rm->r_pos.y || cp->y == rm->r_pos.y + rm->r_max.y - 1)
pp->p_ch = '-';
else
pp->p_ch = '|';
pp->p_flags &= ~F_REAL;
}
else
pp->p_ch = DOOR;
pp->p_ch = DOOR;
}
#ifdef MASTER
@@ -324,31 +324,31 @@ add_pass()
PLACE *pp;
int y, x;
char ch;
for (y = 1; y < NUMLINES - 1; y++)
for (x = 0; x < NUMCOLS; x++)
{
pp = INDEX(y, x);
if ((pp->p_flags & F_PASS) || pp->p_ch == DOOR ||
(!(pp->p_flags&F_REAL) && (pp->p_ch == '|' || pp->p_ch == '-')))
{
ch = pp->p_ch;
if (pp->p_flags & F_PASS)
ch = PASSAGE;
pp->p_flags |= F_SEEN;
move(y, x);
if (pp->p_monst != NULL)
pp->p_monst->t_oldch = pp->p_ch;
else if (pp->p_flags & F_REAL)
addch(ch);
else
{
standout();
addch((pp->p_flags & F_PASS) ? PASSAGE : DOOR);
standend();
}
}
}
for (x = 0; x < NUMCOLS; x++)
{
pp = INDEX(y, x);
if ((pp->p_flags & F_PASS) || pp->p_ch == DOOR ||
(!(pp->p_flags&F_REAL) && (pp->p_ch == '|' || pp->p_ch == '-')))
{
ch = pp->p_ch;
if (pp->p_flags & F_PASS)
ch = PASSAGE;
pp->p_flags |= F_SEEN;
move(y, x);
if (pp->p_monst != NULL)
pp->p_monst->t_oldch = pp->p_ch;
else if (pp->p_flags & F_REAL)
addch(ch);
else
{
standout();
addch((pp->p_flags & F_PASS) ? PASSAGE : DOOR);
standend();
}
}
}
}
#endif
@@ -365,17 +365,17 @@ passnum()
{
struct room *rp;
int i;
pnum = 0;
newpnum = FALSE;
for (rp = passages; rp < &passages[MAXPASS]; rp++)
rp->r_nexits = 0;
rp->r_nexits = 0;
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
for (i = 0; i < rp->r_nexits; i++)
{
newpnum ^= 1;//newpnum++;
numpass(rp->r_exit[i].y, rp->r_exit[i].x);
}
for (i = 0; i < rp->r_nexits; i++)
{
newpnum ^= 1;//newpnum++;
numpass(rp->r_exit[i].y, rp->r_exit[i].x);
}
}
/*
@@ -389,30 +389,30 @@ numpass(int y, int x)
char *fp;
struct room *rp;
char ch;
if (x >= NUMCOLS || x < 0 || y >= NUMLINES || y <= 0)
return;
return;
fp = &flat(y, x);
if (*fp & F_PNUM)
return;
return;
if (newpnum)
{
pnum++;
newpnum = FALSE;
pnum++;
newpnum = FALSE;
}
/*
* check to see if it is a door or secret door, i.e., a new exit,
* or a numerable type of place
*/
if ((ch = chat(y, x)) == DOOR ||
(!(*fp & F_REAL) && (ch == '|' || ch == '-')))
(!(*fp & F_REAL) && (ch == '|' || ch == '-')))
{
rp = &passages[pnum];
rp->r_exit[rp->r_nexits].y = y;
rp->r_exit[rp->r_nexits++].x = x;
rp = &passages[pnum];
rp->r_exit[rp->r_nexits].y = y;
rp->r_exit[rp->r_nexits++].x = x;
}
else if (!(*fp & F_PASS))
return;
return;
*fp |= pnum;
/*
* recurse on the surrounding places

View File

@@ -78,7 +78,6 @@ quaff(struct rogue_state *rs)
}
if (obj == cur_weapon)
cur_weapon = NULL;
/*
* Calculate the effect it has on the poor guy.
*/
@@ -91,7 +90,7 @@ quaff(struct rogue_state *rs)
do_pot(rs,P_CONFUSE, !trip);
when P_POISON:
pot_info[P_POISON].oi_know = TRUE;
if (ISWEARING(R_SUSTSTR))
if (ISWEARING(R_SUSTSTR))
msg(rs,"you feel momentarily sick");
else
{
@@ -112,7 +111,7 @@ quaff(struct rogue_state *rs)
when P_MFIND:
player.t_flags |= SEEMONST;
fuse((void(*)(struct rogue_state *rs,int))turn_see, TRUE, HUHDURATION, AFTER);
if (!turn_see(FALSE))
if (!turn_see(rs,FALSE))
msg(rs,"you have a %s feeling for a moment, then it passes",
choose_str("normal", "strange"));
when P_TFIND:
@@ -158,7 +157,7 @@ quaff(struct rogue_state *rs)
if (!trip)
{
if (on(player, SEEMONST))
turn_see(FALSE);
turn_see(rs,FALSE);
start_daemon(visuals, 0, BEFORE);
seenstairs = seen_stairs();
}
@@ -220,7 +219,7 @@ quaff(struct rogue_state *rs)
call_it(rs,&pot_info[obj->o_which]);
if (discardit)
discard(obj);
discard(obj);
return;
}
@@ -263,47 +262,6 @@ invis_on()
mvaddch(mp->t_pos.y, mp->t_pos.x, mp->t_disguise);
}
/*
* turn_see:
* Put on or off seeing monsters on this level
*/
bool
turn_see(bool turn_off)
{
THING *mp;
bool can_see, add_new;
add_new = FALSE;
for (mp = mlist; mp != NULL; mp = next(mp))
{
move(mp->t_pos.y, mp->t_pos.x);
can_see = see_monst(mp);
if (turn_off)
{
if (!can_see)
addch(mp->t_oldch);
}
else
{
if (!can_see)
standout();
if (!on(player, ISHALU))
addch(mp->t_type);
else
addch(rnd(26) + 'A');
if (!can_see)
{
standend();
add_new ^= 1;//add_new++;
}
}
}
if (turn_off)
player.t_flags &= ~SEEMONST;
else
player.t_flags |= SEEMONST;
return add_new;
}
/*
* seen_stairs:
@@ -358,18 +316,18 @@ do_pot(struct rogue_state *rs,int type, bool knowit)
{
PACT *pp;
int t;
pp = &p_actions[type];
if (!pot_info[type].oi_know)
pot_info[type].oi_know = knowit;
pot_info[type].oi_know = knowit;
t = spread(pp->pa_time);
if (!on(player, pp->pa_flags))
{
player.t_flags |= pp->pa_flags;
fuse(pp->pa_daemon, 0, t, AFTER);
look(rs,FALSE);
player.t_flags |= pp->pa_flags;
fuse(pp->pa_daemon, 0, t, AFTER);
look(rs,FALSE);
}
else
lengthen(pp->pa_daemon, t);
lengthen(pp->pa_daemon, t);
msg(rs,choose_str(pp->pa_high, pp->pa_straight));
}

View File

@@ -23,65 +23,65 @@ ring_on(struct rogue_state *rs)
{
THING *obj;
int ring;
obj = get_item(rs,"put on", RING);
/*
* Make certain that it is somethings that we want to wear
*/
if (obj == NULL)
return;
return;
if (obj->o_type != RING)
{
if (!terse)
msg(rs,"it would be difficult to wrap that around a finger");
else
msg(rs,"not a ring");
return;
if (!terse)
msg(rs,"it would be difficult to wrap that around a finger");
else
msg(rs,"not a ring");
return;
}
/*
* find out which hand to put it on
*/
if (is_current(rs,obj))
return;
return;
if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL)
{
if ((ring = gethand(rs)) < 0)
return;
if ((ring = gethand(rs)) < 0)
return;
}
else if (cur_ring[LEFT] == NULL)
ring = LEFT;
ring = LEFT;
else if (cur_ring[RIGHT] == NULL)
ring = RIGHT;
ring = RIGHT;
else
{
if (!terse)
msg(rs,"you already have a ring on each hand");
else
msg(rs,"wearing two");
return;
if (!terse)
msg(rs,"you already have a ring on each hand");
else
msg(rs,"wearing two");
return;
}
cur_ring[ring] = obj;
/*
* Calculate the effect it has on the poor guy.
*/
switch (obj->o_which)
{
case R_ADDSTR:
chg_str(obj->o_arm);
break;
case R_SEEINVIS:
invis_on();
break;
case R_AGGR:
aggravate(rs);
break;
case R_ADDSTR:
chg_str(obj->o_arm);
break;
case R_SEEINVIS:
invis_on();
break;
case R_AGGR:
aggravate(rs);
break;
}
if (!terse)
addmsg(rs,"you are now wearing ");
addmsg(rs,"you are now wearing ");
msg(rs,"%s (%c)", inv_name(obj, TRUE), obj->o_packch);
}
@@ -95,31 +95,31 @@ ring_off(struct rogue_state *rs)
{
int ring;
THING *obj;
if (cur_ring[LEFT] == NULL && cur_ring[RIGHT] == NULL)
{
if (terse)
msg(rs,"no rings");
else
msg(rs,"you aren't wearing any rings");
return;
if (terse)
msg(rs,"no rings");
else
msg(rs,"you aren't wearing any rings");
return;
}
else if (cur_ring[LEFT] == NULL)
ring = RIGHT;
ring = RIGHT;
else if (cur_ring[RIGHT] == NULL)
ring = LEFT;
ring = LEFT;
else
if ((ring = gethand(rs)) < 0)
return;
if ((ring = gethand(rs)) < 0)
return;
mpos = 0;
obj = cur_ring[ring];
if (obj == NULL)
{
msg(rs,"not wearing such a ring");
return;
msg(rs,"not wearing such a ring");
return;
}
if (dropcheck(rs,obj))
msg(rs,"was wearing %s(%c)", inv_name(obj, TRUE), obj->o_packch);
msg(rs,"was wearing %s(%c)", inv_name(obj, TRUE), obj->o_packch);
}
/*
@@ -130,24 +130,26 @@ int
gethand(struct rogue_state *rs)
{
int c;
for (;;)
{
if (terse)
msg(rs,"left or right ring? ");
else
msg(rs,"left hand or right hand? ");
if ((c = readchar(rs)) == ESCAPE)
return -1;
mpos = 0;
if (c == 'l' || c == 'L')
return LEFT;
else if (c == 'r' || c == 'R')
return RIGHT;
if (terse)
msg(rs,"L or R");
else
msg(rs,"please type L or R");
if ( rs->replaydone != 0 )
return(-1);
if (terse)
msg(rs,"left or right ring? ");
else
msg(rs,"left hand or right hand? ");
if ((c = readchar(rs)) == ESCAPE)
return -1;
mpos = 0;
if (c == 'l' || c == 'L')
return LEFT;
else if (c == 'r' || c == 'R')
return RIGHT;
if (terse)
msg(rs,"L or R");
else
msg(rs,"please type L or R");
}
}
@@ -161,21 +163,21 @@ ring_eat(int hand)
THING *ring;
int eat;
static int uses[] = {
1, /* R_PROTECT */ 1, /* R_ADDSTR */
1, /* R_SUSTSTR */ -3, /* R_SEARCH */
-5, /* R_SEEINVIS */ 0, /* R_NOP */
0, /* R_AGGR */ -3, /* R_ADDHIT */
-3, /* R_ADDDAM */ 2, /* R_REGEN */
-2, /* R_DIGEST */ 0, /* R_TELEPORT */
1, /* R_STEALTH */ 1 /* R_SUSTARM */
1, /* R_PROTECT */ 1, /* R_ADDSTR */
1, /* R_SUSTSTR */ -3, /* R_SEARCH */
-5, /* R_SEEINVIS */ 0, /* R_NOP */
0, /* R_AGGR */ -3, /* R_ADDHIT */
-3, /* R_ADDDAM */ 2, /* R_REGEN */
-2, /* R_DIGEST */ 0, /* R_TELEPORT */
1, /* R_STEALTH */ 1 /* R_SUSTARM */
};
if ((ring = cur_ring[hand]) == NULL)
return 0;
return 0;
if ((eat = uses[ring->o_which]) < 0)
eat = (rnd(-eat) == 0);
eat = (rnd(-eat) == 0);
if (ring->o_which == R_DIGEST)
eat = -eat;
eat = -eat;
return eat;
}
@@ -187,18 +189,18 @@ char *
ring_num(THING *obj)
{
static char buf[10];
if (!(obj->o_flags & ISKNOW))
return "";
return "";
switch (obj->o_which)
{
case R_PROTECT:
case R_ADDSTR:
case R_ADDDAM:
case R_ADDHIT:
sprintf(buf, " [%s]", num(obj->o_arm, 0, RING));
otherwise:
return "";
case R_PROTECT:
case R_ADDSTR:
case R_ADDDAM:
case R_ADDHIT:
sprintf(buf, " [%s]", num(obj->o_arm, 0, RING));
otherwise:
return "";
}
return buf;
}

View File

@@ -238,7 +238,7 @@ death(struct rogue_state *rs,char monst)
//struct tm *localtime(const time_t *);
if ( rs->guiflag == 0 )
{
fprintf(stderr,"death during replay by (%c)\n",monst); //sleep(3);
//fprintf(stderr,"death during replay by (%c)\n",monst); //sleep(3);
rs->replaydone = (uint32_t)time(NULL);
return;
}

View File

@@ -13,6 +13,7 @@
#include <signal.h>
//#include <unistd.h>
//#include <curses.h>
#include "rogue.h"
#ifdef STANDALONE
#include "../komodo/src/komodo_cJSON.h"
@@ -118,20 +119,20 @@ int32_t roguefname(char *fname,uint64_t seed,int32_t counter)
return(0);
}
#ifdef test
int32_t flushkeystrokes(struct rogue_state *rs)
int32_t flushkeystrokes_local(struct rogue_state *rs,int32_t waitflag)
{
#ifndef BUILD_ROGUE
char fname[1024]; FILE *fp; int32_t i,retflag = -1;
rs->counter++;
roguefname(fname,rs->seed,rs->counter);
if ( (fp= fopen(fname,"wb")) != 0 )
{
if ( fwrite(rs->buffered,1,rs->num,fp) == rs->num )
{
rs->counter++;
rs->num = 0;
retflag = 0;
fclose(fp);
if ( (fp= fopen("savefile","wb")) != 0 )
/*if ( (fp= fopen("savefile","wb")) != 0 )
{
save_file(rs,fp,0);
if ( 0 && (fp= fopen("savefile","rb")) != 0 )
@@ -140,22 +141,24 @@ int32_t flushkeystrokes(struct rogue_state *rs)
fprintf(stderr,"%02x",fgetc(fp));
fprintf(stderr," first part rnd.%d\n",rnd(1000));
fclose(fp);
}
roguefname(fname,rs->seed,rs->counter);
}*/
roguefname(fname,rs->seed,rs->counter+1);
if ( (fp= fopen(fname,"wb")) != 0 ) // truncate next file
fclose(fp);
//fprintf(stderr,"savefile <- %s retflag.%d\n",fname,retflag);
}
//}
} else fprintf(stderr,"error writing (%s)\n",fname);
} else fprintf(stderr,"error creating (%s)\n",fname);
return(retflag);
}
#else
return(0);
#endif
}
#ifdef BUILD_ROGUE
// stubs for inside daemon
void rogue_progress(struct rogue_state *rs,uint64_t seed,char *keystrokes,int32_t num)
void rogue_progress(struct rogue_state *rs,int32_t waitflag,uint64_t seed,char *keystrokes,int32_t num)
{
}
@@ -165,14 +168,19 @@ int32_t rogue_setplayerdata(struct rogue_state *rs,char *gametxidstr)
}
#endif
int32_t flushkeystrokes(struct rogue_state *rs)
int32_t flushkeystrokes(struct rogue_state *rs,int32_t waitflag)
{
if ( rs->num > 0 )
{
rogue_progress(rs,rs->seed,rs->buffered,rs->num);
// need to get existing keystrokes including mempool
// create keystrokes that are not saved
//rs->keytxid = rogue_progress(rs,waitflag,rs->seed,&rs->buffered[rs->lastnum],rs->num - rs->lastnum);
//rs->lastnum = rs->num;
rogue_progress(rs,waitflag,rs->seed,rs->buffered,rs->num);
flushkeystrokes_local(rs,waitflag);
memset(rs->buffered,0,sizeof(rs->buffered));
rs->counter++;
rs->num = 0;
//rs->num = 0;
//rs->counter++;
}
return(0);
}
@@ -180,7 +188,7 @@ int32_t flushkeystrokes(struct rogue_state *rs)
void rogue_bailout(struct rogue_state *rs)
{
char cmd[512];
flushkeystrokes(rs);
flushkeystrokes(rs,1);
//sleep(5);
return;
/*fprintf(stderr,"bailing out\n");
@@ -189,6 +197,12 @@ void rogue_bailout(struct rogue_state *rs)
fprintf(stderr,"error issuing (%s)\n",cmd);*/
}
#ifdef _WIN32
#ifdef _MSC_VER
#define sleep(x) Sleep(1000*(x))
#endif
#endif
int32_t rogue_replay2(uint8_t *newdata,uint64_t seed,char *keystrokes,int32_t num,struct rogue_player *player,int32_t sleepmillis)
{
struct rogue_state *rs; FILE *fp; int32_t i,n;
@@ -208,6 +222,14 @@ int32_t rogue_replay2(uint8_t *newdata,uint64_t seed,char *keystrokes,int32_t nu
globalR = *rs;
uint32_t starttime = (uint32_t)time(NULL);
rogueiterate(rs);
/*
// keypress after replay
printf("[Press return to continue]");
fflush(stdout);
if (fgets(prbuf, 10, stdin) != 0);
*/
if ( 0 )
{
fprintf(stderr,"elapsed %d seconds\n",(uint32_t)time(NULL) - starttime);
@@ -229,7 +251,7 @@ int32_t rogue_replay2(uint8_t *newdata,uint64_t seed,char *keystrokes,int32_t nu
if ( (fp= fopen("checkfile","wb")) != 0 )
{
save_file(rs,fp,0);
fprintf(stderr,"gold.%d hp.%d strength.%d/%d level.%d exp.%d dungeon.%d data[%d]\n",rs->P.gold,rs->P.hitpoints,rs->P.strength&0xffff,rs->P.strength>>16,rs->P.level,rs->P.experience,rs->P.dungeonlevel,rs->playersize);
//fprintf(stderr,"gold.%d hp.%d strength.%d/%d level.%d exp.%d dungeon.%d data[%d]\n",rs->P.gold,rs->P.hitpoints,rs->P.strength&0xffff,rs->P.strength>>16,rs->P.level,rs->P.experience,rs->P.dungeonlevel,rs->playersize);
if ( newdata != 0 && rs->playersize > 0 )
memcpy(newdata,rs->playerdata,rs->playersize);
}
@@ -237,7 +259,6 @@ int32_t rogue_replay2(uint8_t *newdata,uint64_t seed,char *keystrokes,int32_t nu
free(rs);
return(n);
}
#endif
long get_filesize(FILE *fp)
{
@@ -248,11 +269,10 @@ long get_filesize(FILE *fp)
return(fsize);
}
int32_t rogue_replay(uint64_t seed,int32_t sleeptime)
char *rogue_keystrokesload(int32_t *numkeysp,uint64_t seed,int32_t counter)
{
FILE *fp; char fname[1024]; char *keystrokes = 0; long num=0,fsize; int32_t i,counter = 0; struct rogue_state *rs; struct rogue_player P,*player = 0;
if ( seed == 0 )
seed = 777;
char fname[1024],*keystrokes = 0; FILE *fp; long fsize; int32_t num = 0;
*numkeysp = 0;
while ( 1 )
{
roguefname(fname,seed,counter);
@@ -262,26 +282,37 @@ int32_t rogue_replay(uint64_t seed,int32_t sleeptime)
if ( (fsize= get_filesize(fp)) <= 0 )
{
fclose(fp);
printf("fsize.%ld\n",fsize);
//printf("fsize.%ld\n",fsize);
break;
}
if ( (keystrokes= (char *)realloc(keystrokes,num+fsize)) == 0 )
{
fprintf(stderr,"error reallocating keystrokes\n");
fclose(fp);
return(-1);
return(0);
}
if ( fread(&keystrokes[num],1,fsize,fp) != fsize )
{
fprintf(stderr,"error reading keystrokes from (%s)\n",fname);
fclose(fp);
return(-1);
free(keystrokes);
return(0);
}
fclose(fp);
num += fsize;
counter++;
fprintf(stderr,"loaded %ld from (%s) total %ld\n",fsize,fname,num);
//fprintf(stderr,"loaded %ld from (%s) total %d\n",fsize,fname,num);
}
*numkeysp = num;
return(keystrokes);
}
int32_t rogue_replay(uint64_t seed,int32_t sleeptime)
{
FILE *fp; char fname[1024]; char *keystrokes = 0; long fsize; int32_t i,num=0,counter = 0; struct rogue_state *rs; struct rogue_player P,*player = 0;
if ( seed == 0 )
seed = 777;
keystrokes = rogue_keystrokesload(&num,seed,counter);
if ( num > 0 )
{
sprintf(fname,"rogue.%llu.player",(long long)seed);
@@ -295,7 +326,6 @@ int32_t rogue_replay(uint64_t seed,int32_t sleeptime)
fclose(fp);
}
rogue_replay2(0,seed,keystrokes,num,player,sleeptime);
mvaddstr(LINES - 2, 0, (char *)"replay completed");
endwin();
my_exit(0);
@@ -313,8 +343,17 @@ int rogue(int argc, char **argv, char **envp)
rs->sleeptime = 1; // non-zero to allow refresh()
if ( argc == 3 && strlen(argv[2]) == 64 )
{
rs->seed = atol(argv[1]);
#ifdef _WIN32
#ifdef _MSC_VER
rs->seed = _strtoui64(argv[1], NULL, 10);
#else
rs->seed = atol(argv[1]); // windows, but not MSVC
#endif // _MSC_VER
#else
rs->seed = atol(argv[1]); // non-windows
#endif // _WIN32
strcpy(Gametxidstr,argv[2]);
fprintf(stderr,"setplayerdata\n");
if ( rogue_setplayerdata(rs,Gametxidstr) < 0 )
{
fprintf(stderr,"invalid gametxid, or already started\n");
@@ -410,7 +449,7 @@ int rogue(int argc, char **argv, char **envp)
#endif
printf("Hello %s, just a moment while I dig the dungeon... seed.%llu", whoami,(long long)rs->seed);
fflush(stdout);
fprintf(stderr,"rogueiterate\n");
rogueiterate(rs);
return(0);
}
@@ -510,6 +549,18 @@ tstp(int ignored)
#endif*/
}
#ifdef _WIN32
#ifdef _MSC_VER
void usleep(int32_t micros)
{
if (micros < 1000)
Sleep(1);
else Sleep(micros / 1000);
}
#endif
#endif
/*
* playit:
* The main loop of the program. Loop until the game is over,
@@ -560,15 +611,15 @@ playit(struct rogue_state *rs)
}
else
{
if ( rs->needflush != 0 && rs->num > 1000 )
if ( rs->needflush != 0 )
{
if ( flushkeystrokes(rs) == 0 )
if ( flushkeystrokes(rs,0) == 0 )
rs->needflush = 0;
}
}
}
if ( rs->guiflag != 0 )
flushkeystrokes(rs);
flushkeystrokes(rs,1);
endit(0);
}
@@ -593,13 +644,13 @@ int32_t _quit()
if ( rs->sleeptime != 0 )
refresh();
score(rs,purse, 1, 0);
flushkeystrokes(rs);
flushkeystrokes(rs,1);
my_exit(0);
}
else
{
//score(rs,purse, 1, 0);
fprintf(stderr,"done! (%c)\n",c);
//fprintf(stderr,"done! (%c)\n",c);
}
return(1);
}

View File

@@ -362,11 +362,12 @@ typedef union _bits256 bits256;
struct rogue_state
{
uint64_t seed;
char *keystrokes;
char *keystrokes,*keystrokeshex;
uint32_t needflush,replaydone;
int32_t numkeys,ind,num,guiflag,counter,sleeptime,playersize,restoring;
int32_t numkeys,ind,num,guiflag,counter,sleeptime,playersize,restoring,lastnum;
FILE *logfp;
struct rogue_player P;
char buffered[8192];
char buffered[10000];
uint8_t playerdata[10000];
};
extern struct rogue_state globalR;
@@ -374,12 +375,12 @@ extern struct rogue_state globalR;
int rogue(int argc, char **argv, char **envp);
void rogueiterate(struct rogue_state *rs);
int32_t roguefname(char *fname,uint64_t seed,int32_t counter);
int32_t flushkeystrokes(struct rogue_state *rs);
int32_t flushkeystrokes(struct rogue_state *rs,int32_t waitflag);
int32_t rogue_restorepack(struct rogue_state *rs);
void restore_player(struct rogue_state *rs);
int32_t rogue_replay2(uint8_t *newdata,uint64_t seed,char *keystrokes,int32_t num,struct rogue_player *player,int32_t sleepmillis);
void rogue_bailout(struct rogue_state *rs);
void rogue_progress(struct rogue_state *rs,uint64_t seed,char *keystrokes,int32_t num);
void rogue_progress(struct rogue_state *rs,int32_t waitflag,uint64_t seed,char *keystrokes,int32_t num);
int32_t rogue_setplayerdata(struct rogue_state *rs,char *gametxidstr);
#define ROGUE_MAXTOTAL (pstats.s_str*2)
@@ -612,7 +613,7 @@ void current(struct rogue_state *rs,THING *cur, char *how, char *where);
void d_level(struct rogue_state *rs);
void death(struct rogue_state *rs,char monst);
char death_monst(void);
void dig(int y, int x);
void dig(struct rogue_state *rs,int y, int x);
void discard(THING *item);
void discovered(struct rogue_state *rs);
int dist(int y1, int x1, int y2, int x2);
@@ -620,7 +621,7 @@ int dist_cp(coord *c1, coord *c2);
int do_chase(struct rogue_state *rs,THING *th);
void do_daemons(struct rogue_state *rs,int flag);
void do_fuses(struct rogue_state *rs,int flag);
void do_maze(struct room *rp);
void do_maze(struct rogue_state *rs,struct room *rp);
void do_motion(struct rogue_state *rs,THING *obj, int ydelta, int xdelta);
void do_move(struct rogue_state *rs,int dy, int dx);
void do_passages(struct rogue_state *rs);
@@ -632,7 +633,7 @@ void doadd(struct rogue_state *rs,char *fmt, va_list args);
void door(struct room *rm, coord *cp);
void door_open(struct rogue_state *rs,struct room *rp);
void drain(struct rogue_state *rs);
void draw_room(struct room *rp);
void draw_room(struct rogue_state *rs,struct room *rp);
void drop(struct rogue_state *rs);
void eat(struct rogue_state *rs);
size_t encread(char *start, size_t size, FILE *inf);
@@ -761,7 +762,7 @@ bool chase(THING *tp, coord *ee);
bool diag_ok(coord *sp, coord *ep);
bool dropcheck(struct rogue_state *rs,THING *obj);
bool fallpos(coord *pos, coord *newpos);
bool find_floor(struct room *rp, coord *cp, int limit, bool monst);
bool find_floor(struct rogue_state *rs,struct room *rp, coord *cp, int limit, bool monst);
bool is_magic(THING *obj);
bool is_symlink(char *sp);
bool levit_check(struct rogue_state *rs);
@@ -770,7 +771,7 @@ bool roll_em(THING *thatt, THING *thdef, THING *weap, bool hurl);
bool see_monst(THING *mp);
bool seen_stairs(void);
bool turn_ok(int y, int x);
bool turn_see(bool turn_off);
bool turn_see(struct rogue_state *rs,bool turn_off);
bool is_current(struct rogue_state *rs,THING *obj);
int passwd(void);
@@ -824,6 +825,7 @@ void doctor(struct rogue_state *rs,int);
void playit(struct rogue_state *rs);
struct room *roomin(struct rogue_state *rs,coord *cp);
int32_t thing_find(THING *ptr);
#define MAXDAEMONS 20

View File

@@ -1,17 +1,25 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual C++ Express 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rogue54", "rogue54.vcproj", "{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}"
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rogue54", "rogue54.vcxproj", "{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Debug|Win32.ActiveCfg = Debug|Win32
{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Debug|Win32.Build.0 = Debug|Win32
{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Debug|x64.ActiveCfg = Debug|x64
{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Debug|x64.Build.0 = Debug|x64
{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Release|Win32.ActiveCfg = Release|Win32
{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Release|Win32.Build.0 = Release|Win32
{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Release|x64.ActiveCfg = Release|x64
{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -0,0 +1,257 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{9EA0D326-8097-4ADA-82EA-4DB1F5CAA8F6}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC70.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC70.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC70.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC70.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>14.0.25431.1</_ProjectFileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>Debug\</OutDir>
<IntDir>Debug\</IntDir>
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>Release\</OutDir>
<IntDir>Release\</IntDir>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
<AdditionalIncludeDirectories>../pdcurses;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;ALLSCORES;MASTER;SCOREFILE="rogue54.scr";LOCKFILE="rogue54.lck";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling />
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<DisableLanguageExtensions>false</DisableLanguageExtensions>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<PrecompiledHeader />
<BrowseInformation />
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<AdditionalDependencies>Ws2_32.lib;pdcurses.lib;advapi32.lib;shfolder.lib;user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)rogue54.exe</OutputFile>
<AdditionalLibraryDirectories>..\pdcurses;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)rogue54.pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
<AdditionalIncludeDirectories>$(ProjectDir)x86_64-w64-msvc\deps\install\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;PDC_DLL_BUILD;PDC_WIDE;PDCDEBUG;_CRT_SECURE_NO_DEPRECATE;ALLSCORES;SCOREFILE="rogue54.scr";LOCKFILE="rogue54.lck";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling>
</ExceptionHandling>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<DisableLanguageExtensions>false</DisableLanguageExtensions>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<PrecompiledHeader>
</PrecompiledHeader>
<BrowseInformation>
</BrowseInformation>
<WarningLevel>Level4</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<AdditionalDependencies>Ws2_32.lib;wincon\pdcurses.lib;libcurl_imp.lib;advapi32.lib;shfolder.lib;user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)rogue54.exe</OutputFile>
<AdditionalLibraryDirectories>$(ProjectDir)x86_64-w64-msvc\deps\install\lib;$(ProjectDir)x86_64-w64-msvc\deps\install\Release\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)rogue54.pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<OmitFramePointers>true</OmitFramePointers>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>$(ProjectDir)\x86_64-w64-msvc\include\ncursesw;$(ProjectDir)\x86_64-w64-msvc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<OutputFile>$(OutDir)rogue54.exe</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<OmitFramePointers>true</OmitFramePointers>
<PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;PDC_DLL_BUILD;PDC_WIDE;PDCDEBUG;_CRT_SECURE_NO_DEPRECATE;ALLSCORES;SCOREFILE="rogue54.scr";LOCKFILE="rogue54.lck";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>$(ProjectDir)x86_64-w64-msvc\deps\install\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeaderFile>stdafx.h</PrecompiledHeaderFile>
<CompileAs>CompileAsC</CompileAs>
<ExceptionHandling />
<BrowseInformation />
</ClCompile>
<Link>
<OutputFile>$(OutDir)rogue54.exe</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<AdditionalLibraryDirectories>$(ProjectDir)x86_64-w64-msvc\deps\install\lib;$(ProjectDir)x86_64-w64-msvc\deps\install\Release\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>Ws2_32.lib;wincon\pdcurses.lib;libcurl_imp.lib;advapi32.lib;shfolder.lib;user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<ForceSymbolReferences>%(ForceSymbolReferences)</ForceSymbolReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="armor.c" />
<ClCompile Include="chase.c" />
<ClCompile Include="command.c" />
<ClCompile Include="daemon.c" />
<ClCompile Include="daemons.c" />
<ClCompile Include="extern.c" />
<ClCompile Include="fight.c" />
<ClCompile Include="init.c" />
<ClCompile Include="io.c" />
<ClCompile Include="list.c" />
<ClCompile Include="mach_dep.c" />
<ClCompile Include="main.c" />
<ClCompile Include="mdport.c" />
<ClCompile Include="misc.c" />
<ClCompile Include="monsters.c" />
<ClCompile Include="move.c" />
<ClCompile Include="new_level.c" />
<ClCompile Include="options.c" />
<ClCompile Include="pack.c" />
<ClCompile Include="passages.c" />
<ClCompile Include="potions.c" />
<ClCompile Include="rings.c" />
<ClCompile Include="rip.c" />
<ClCompile Include="rogue.c" />
<ClCompile Include="rooms.c" />
<ClCompile Include="save.c" />
<ClCompile Include="scrolls.c" />
<ClCompile Include="state.c" />
<ClCompile Include="sticks.c" />
<ClCompile Include="things.c" />
<ClCompile Include="vers.c" />
<ClCompile Include="weapons.c" />
<ClCompile Include="wizard.c" />
<ClCompile Include="xcrypt.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="extern.h" />
<ClInclude Include="rogue.h" />
<ClInclude Include="score.h" />
</ItemGroup>
<ItemGroup>
<Text Include="LICENSE.TXT" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,64 @@
@echo off
echo Rogue Build Script by Decker (c) 2019
@REM Check for Visual Studio
call set "VSPATH="
if defined VS140COMNTOOLS ( if not defined VSPATH (
call set "VSPATH=%%VS140COMNTOOLS%%"
) )
@REM check if we already have the tools in the environment
if exist "%VCINSTALLDIR%" (
goto compile
)
if not defined VSPATH (
echo You need Microsoft Visual Studio 15 installed
pause
exit
)
@REM set up the environment
if exist "%VSPATH%..\..\vc\vcvarsall.bat" (
call "%%VSPATH%%..\..\vc\vcvarsall.bat" amd64
goto compile
)
echo Unable to set up the environment
pause
exit
:compile
mkdir x86_64-w64-msvc\deps
mkdir x86_64-w64-msvc\deps\install
pushd x86_64-w64-msvc\deps
:compile_pdcurses
rem git clone https://github.com/wmcbrine/PDCurses PDCurses.org
git clone https://github.com/Bill-Gray/PDCurses
set PREFIX_DIR=%CD%\install
pushd PDCurses
mkdir build64 & pushd build64
rem cmake -G"Visual Studio 14 2015 Win64" -DPDC_WIDE=ON -DCMAKE_INSTALL_PREFIX=%PREFIX_DIR% -DCMAKE_BUILD_TYPE=Debug -DPDCDEBUG=ON ..
cmake -G"Visual Studio 14 2015 Win64" -DPDC_WIDE=ON -DCMAKE_INSTALL_PREFIX=%PREFIX_DIR% -DCMAKE_BUILD_TYPE=Release ..
popd
rem cmake --build build64 --config Debug --target install
cmake --build build64 --config Release --target install
popd
:compile_curl
git clone https://github.com/curl/curl
pushd curl
mkdir build64 & pushd build64
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_INSTALL_PREFIX=%PREFIX_DIR% -DCMAKE_USE_WINSSL:BOOL=ON ..
cmake --build . --config Release --target libcurl
cmake --build . --config Release --target install
popd
popd

View File

@@ -112,7 +112,7 @@ do_rooms(struct rogue_state *rs)
rp->r_pos.x = top.x + rnd(bsze.x - rp->r_max.x);
rp->r_pos.y = top.y + rnd(bsze.y - rp->r_max.y);
} until (rp->r_pos.y != 0);
draw_room(rp);
draw_room(rs,rp);
/*
* Put the gold in
*/
@@ -122,7 +122,7 @@ do_rooms(struct rogue_state *rs)
gold = new_item();
gold->o_goldval = rp->r_goldval = GOLDCALC;
find_floor(rp, &rp->r_gold, FALSE, FALSE);
find_floor(rs,rp, &rp->r_gold, FALSE, FALSE);
gold->o_pos = rp->r_gold;
chat(rp->r_gold.y, rp->r_gold.x) = GOLD;
gold->o_flags = ISMANY;
@@ -136,7 +136,7 @@ do_rooms(struct rogue_state *rs)
if (rnd(100) < (rp->r_goldval > 0 ? 80 : 25))
{
tp = new_item();
find_floor(rp, &mp, FALSE, TRUE);
find_floor(rs,rp, &mp, FALSE, TRUE);
new_monster(rs,tp, randmonster(FALSE), &mp);
give_pack(rs,tp);
}
@@ -150,12 +150,12 @@ do_rooms(struct rogue_state *rs)
*/
void
draw_room(struct room *rp)
draw_room(struct rogue_state *rs,struct room *rp)
{
int y, x;
if (rp->r_flags & ISMAZE)
do_maze(rp);
do_maze(rs,rp);
else
{
vert(rp, rp->r_pos.x); /* Draw left side */
@@ -211,7 +211,7 @@ static SPOT maze[NUMLINES/3+1][NUMCOLS/3+1];
void
do_maze(struct room *rp)
do_maze(struct rogue_state *rs,struct room *rp)
{
SPOT *sp;
int starty, startx;
@@ -232,7 +232,7 @@ do_maze(struct room *rp)
pos.y = starty + Starty;
pos.x = startx + Startx;
putpass(&pos);
dig(starty, startx);
dig(rs,starty, startx);
}
/*
@@ -241,7 +241,7 @@ do_maze(struct room *rp)
*/
void
dig(int y, int x)
dig(struct rogue_state *rs,int y, int x)
{
coord *cp;
int cnt, newy, newx, nexty = 0, nextx = 0;
@@ -252,6 +252,8 @@ dig(int y, int x)
for (;;)
{
if ( rs->replaydone != 0 )
return;
cnt = 0;
for (cp = del; cp <= &del[3]; cp++)
{
@@ -291,7 +293,7 @@ dig(int y, int x)
pos.y = nexty + Starty;
pos.x = nextx + Startx;
putpass(&pos);
dig(nexty, nextx);
dig(rs,nexty, nextx);
}
}
@@ -332,7 +334,7 @@ rnd_pos(struct room *rp, coord *cp)
* pick a new room each time around the loop.
*/
bool
find_floor(struct room *rp, coord *cp, int limit, bool monst)
find_floor(struct rogue_state *rs,struct room *rp, coord *cp, int limit, bool monst)
{
PLACE *pp;
int cnt;
@@ -346,6 +348,8 @@ find_floor(struct room *rp, coord *cp, int limit, bool monst)
cnt = limit;
for (;;)
{
if ( rs->replaydone != 0 )
return(FALSE);
if (limit && cnt-- == 0)
return FALSE;
if (pickroom)

View File

@@ -313,7 +313,7 @@ def:
call_it(rs,&scr_info[obj->o_which]);
if (discardit)
discard(obj);
discard(obj);
}
/*

View File

@@ -1429,6 +1429,11 @@ rs_write_object(struct rogue_state *rs,FILE *savef, THING *o)
struct rogue_packitem *item;
if (write_error)
return(WRITESTAT);
if ( thing_find(o) < 0 )
{
fprintf(stderr,"cant find thing.%p (%s) in list\n",o,inv_name(o,FALSE)); //sleep(3);
return(0);
}
if ( o->_o._o_packch != 0 )
{
item = &rs->P.roguepack[rs->P.packsize];

View File

@@ -158,7 +158,7 @@ do_zap(struct rogue_state *rs)
{
do
{
find_floor(NULL, &new_pos, FALSE, TRUE);
find_floor(rs,NULL, &new_pos, FALSE, TRUE);
} while (ce(new_pos, hero));
}
else

View File

@@ -81,6 +81,8 @@ do_motion(struct rogue_state *rs,THING *obj, int ydelta, int xdelta)
obj->o_pos = hero;
for (;;)
{
if ( rs->replaydone != 0 )
return;
/*
* Erase the old one
*/
@@ -127,28 +129,28 @@ fall(struct rogue_state *rs,THING *obj, bool pr)
if (fallpos(&obj->o_pos, &fpos))
{
pp = INDEX(fpos.y, fpos.x);
pp->p_ch = (char) obj->o_type;
obj->o_pos = fpos;
if (cansee(rs,fpos.y, fpos.x))
{
if (pp->p_monst != NULL)
pp->p_monst->t_oldch = (char) obj->o_type;
else
mvaddch(fpos.y, fpos.x, obj->o_type);
}
attach(lvl_obj, obj);
return;
pp = INDEX(fpos.y, fpos.x);
pp->p_ch = (char) obj->o_type;
obj->o_pos = fpos;
if (cansee(rs,fpos.y, fpos.x))
{
if (pp->p_monst != NULL)
pp->p_monst->t_oldch = (char) obj->o_type;
else
mvaddch(fpos.y, fpos.x, obj->o_type);
}
attach(lvl_obj, obj);
return;
}
if (pr)
{
if (has_hit)
{
endmsg(rs);
has_hit = FALSE;
}
msg(rs,"the %s vanishes as it hits the ground",
weap_info[obj->o_which].oi_name);
if (has_hit)
{
endmsg(rs);
has_hit = FALSE;
}
msg(rs,"the %s vanishes as it hits the ground",
weap_info[obj->o_which].oi_name);
}
discard(obj);
}

View File

@@ -35,19 +35,21 @@ whatis(struct rogue_state *rs,bool insist, int type)
for (;;)
{
obj = get_item(rs,"identify", type);
if (insist)
{
if (n_objs == 0)
return;
else if (obj == NULL)
msg(rs,"you must identify something");
else if (type && obj->o_type != type &&
!(type == R_OR_S && (obj->o_type == RING || obj->o_type == STICK)) )
msg(rs,"you must identify a %s", type_name(type));
else
break;
}
if ( rs->replaydone != 0 )
return;
obj = get_item(rs,"identify", type);
if (insist)
{
if (n_objs == 0)
return;
else if (obj == NULL)
msg(rs,"you must identify something");
else if (type && obj->o_type != type &&
!(type == R_OR_S && (obj->o_type == RING || obj->o_type == STICK)) )
msg(rs,"you must identify a %s", type_name(type));
else
break;
}
else
break;
}
@@ -202,7 +204,7 @@ teleport(struct rogue_state *rs)
static coord c;
mvaddch(hero.y, hero.x, floor_at());
find_floor((struct room *) NULL, &c, FALSE, TRUE);
find_floor(rs,(struct room *) NULL, &c, FALSE, TRUE);
if (roomin(rs,&c) != proom)
{
leave_room(rs,&hero);

View File

@@ -0,0 +1,265 @@
/* Many of the following #defines are completely unused for the
nonce. For each character, its code point in code page 437,
Unicode, and page 8859-1 are given. The first is used for
non-wide builds in Win32 console, DOS, SDL, and OS/2.
Unicode is used for all wide builds, and for the non-wide
build of WinGUI. Code page 8859-1 is used for non-wide X11.
All of these characters exist in CP437 and Unicode. Some
don't exist in 8859-1, in which case the last column is 'TBD'.
Only 32 are used in ncurses. So caution is advised. */
#ifdef USE_ISO8859_CHARSET
#define CHOOSE( A, B, C) (C)
#define TBD '!'
#else
#define CHOOSE( A, B, C) (USE_UNICODE_ACS_CHARS ? B : A)
#endif
/* Codes found from https://en.wikipedia.org/wiki/Code_page_437 */
#define SMILE CHOOSE( 0x01, 0x263a, 'O')
#define REV_SMILE CHOOSE( 0x02, 0x263b, 'O')
#define HEART CHOOSE( 0x03, 0x2665, 'H')
#define DIAMOND CHOOSE( 0x04, 0x2666, 0x01)
#define CLUB CHOOSE( 0x05, 0x2663, 'C')
#define SPADE CHOOSE( 0x06, 0x2660, 'S')
#define MEDIUM_BULLET CHOOSE( 0x07, 0x2022, 0xb7)
#define REV_BULLET CHOOSE( 0x08, 0x2508, 0xb7)
#define WHITE_BULLET CHOOSE( 0x09, 0x25cb, 7)
#define REV_WHITE_BULLET CHOOSE( 0x0a, 0x25D9, 7)
#define MALE_SYM CHOOSE( 0x0b, 0x2642, 'm')
#define FEMALE_SYM CHOOSE( 0x0c, 0x2640, 'f')
#define QTR_NOTE CHOOSE( 0x0d, 0x266a, 0xbc)
#define EIGHTH_NOTE CHOOSE( 0x0e, 0x266b, 0xbd)
#define SPLAT CHOOSE( 0x0f, 0xa4 , 0xa4)
#define RIGHT_TRIANGLE CHOOSE( 0x10, 0x25b6, '>')
#define LEFT_TRIANGLE CHOOSE( 0x11, 0x25c0, '<')
#define UP_DOWN_ARROW CHOOSE( 0x12, 0x2195, 0x19)
#define DBL_BANG CHOOSE( 0x13, 0x203c, '!')
#define PILCROW CHOOSE( 0x14, 0xb6 , 0xb6)
#define SECTION_SIGN CHOOSE( 0x15, 0xa7 , 0xa7)
#define LOW_QTR_BLOCK CHOOSE( 0x16, 0x25b2, '_')
#define UP_DOWN_ARROW_UNDERSCORED CHOOSE( 0x17, 0x21ab, 0x19)
#define UP_ARROW CHOOSE( 0x18, 0x2191, '^')
#define DOWN_ARROW CHOOSE( 0x19, 0x2193, 'v')
#define RIGHT_ARROW CHOOSE( 0x1a, 0x2192, '>')
#define LEFT_ARROW CHOOSE( 0x1b, 0x2190, '<')
#define RIGHT_ANGLE CHOOSE( 0x1c, 0x221f, 0xe)
#define LEFT_RIGHT_ARROW CHOOSE( 0x1d, 0x2194, '-')
#define UP_TRIANGLE CHOOSE( 0x1e, 0x25b2, '^')
#define DOWN_TRIANGLE CHOOSE( 0x1f, 0x25bc, 'v')
#define UPPERCASE_C_CEDILLA CHOOSE( 0x80, 0xc7 , 0xc7)
#define LOWERCASE_U_UMLAUT CHOOSE( 0x81, 0xfc , 0xfc)
#define LOWERCASE_E_ACUTE CHOOSE( 0x82, 0xe9 , 0xe9)
#define LOWERCASE_A_CIRCUMFLEX CHOOSE( 0x83, 0xe2 , 0xe2)
#define LOWERCASE_A_UMLAUT CHOOSE( 0x84, 0xe4 , 0xe4)
#define LOWERCASE_A_GRAVE CHOOSE( 0x85, 0xe0 , 0xea)
#define LOWERCASE_A_RING CHOOSE( 0x86, 0xe5 , 0xe5)
#define LOWERCASE_C_CEDILLA CHOOSE( 0x87, 0xe7 , 0xe7)
#define LOWERCASE_E_CIRCUMFLEX CHOOSE( 0x88, 0xea , 0xea)
#define LOWERCASE_E_UMLAUT CHOOSE( 0x89, 0xeb , 0xeb)
#define LOWERCASE_E_GRAVE CHOOSE( 0x8a, 0xe8 , 0xe8)
#define LOWERCASE_I_UMLAUT CHOOSE( 0x8b, 0xef , 0xef)
#define LOWERCASE_I_CIRCUMFLEX CHOOSE( 0x8c, 0xee , 0xee)
#define LOWERCASE_I_GRAVE CHOOSE( 0x8d, 0xec , 0xce)
#define UPPERCASE_A_UMLAUT CHOOSE( 0x8e, 0xc4 , 0xc4)
#define UPPERCASE_A_RING CHOOSE( 0x8f, 0xc5 , 0xc5)
#define UPPERCASE_E_ACUTE CHOOSE( 0x90, 0xc9 , 0xc9)
#define LOWERCASE_AE_LIGATURE CHOOSE( 0x91, 0xe6 , 0xe6)
#define UPPERCASE_AE_LIGATURE CHOOSE( 0x92, 0xc6 , 0xc6)
#define LOWERCASE_O_CIRCUMFLEX CHOOSE( 0x93, 0xf4 , 0xf4)
#define LOWERCASE_O_UMLAUT CHOOSE( 0x94, 0xf6 , 0xf6)
#define LOWERCASE_O_GRAVE CHOOSE( 0x95, 0xf2 , 0xf2)
#define LOWERCASE_U_CIRCUMFLEX CHOOSE( 0x96, 0xfb , 0xfb)
#define LOWERCASE_U_GRAVE CHOOSE( 0x97, 0xf9 , 0xf9)
#define LOWERCASE_Y_UMLAUT CHOOSE( 0x98, 0xff , 0xff)
#define UPPERCASE_O_UMLAUT CHOOSE( 0x99, 0xd6 , 0xd6)
#define UPPERCASE_U_UMLAUT CHOOSE( 0x9a, 0xdc , 0xdc)
#define CENT_SIGN CHOOSE( 0x9b, 0xa2 , 0xa2)
#define STERLING_SIGN CHOOSE( 0x9c, 0xa3 , 30)
#define YEN_SIGN CHOOSE( 0x9d, 0xa5 , 0xa5)
#define PESETA_SIGN CHOOSE( 0x9e, 0x20a7, TBD)
#define F_WITH_HOOK CHOOSE( 0x9f, 0x0192, TBD)
#define LOWERCASE_A_ACUTE CHOOSE( 0xa0, 0xe1 , 0xe1)
#define LOWERCASE_I_ACUTE CHOOSE( 0xa1, 0xed , 0xed)
#define LOWERCASE_O_ACUTE CHOOSE( 0xa2, 0xf3 , 0xf3)
#define LOWERCASE_U_ACUTE CHOOSE( 0xa3, 0xfa , 0xfa)
#define LOWERCASE_N_TILDE CHOOSE( 0xa4, 0xf1 , 0xf1)
#define UPPERCASE_N_TILDE CHOOSE( 0xa5, 0xd1 , 0xd1)
#define A_ORDINAL CHOOSE( 0xa6, 0xaa , 0xaa)
#define O_ORDINAL CHOOSE( 0xa7, 0xba , 0xba)
#define INVERTED_QUESTION_MARK CHOOSE( 0xa8, 0xbf , 0xbf)
#define REVERSED_NOT_SIGN CHOOSE( 0xa9, 0x2310, TBD)
#define NOT_SIGN CHOOSE( 0xaa, 0xac , 0xac)
#define VULGAR_HALF CHOOSE( 0xab, 0xbd , 0xbd)
#define VULGAR_QUARTER CHOOSE( 0xac, 0xbc , 0xbc)
#define INVERTED_EXCLAMATION_MARK CHOOSE( 0xad, 0xa1 , 0xa1)
#define LEFT_ANGLE_QUOTE_MARK CHOOSE( 0xae, 0xab , 0xab)
#define RIGHT_ANGLE_QUOTE_MARK CHOOSE( 0xaf, 0xbb , 0xbb)
#define LIGHT_SHADE CHOOSE( 0xb0, 0x2591, '#' )
#define MEDIUM_SHADE CHOOSE( 0xb1, 0x2592, 2)
#define DARK_SHADE CHOOSE( 0xb2, 0x2593, TBD)
#define BOX_VLINE CHOOSE( 0xb3, 0x2502, 25)
#define BOX_RTEE CHOOSE( 0xb4, 0x2524, 22)
#define BOX_SD_RTEE CHOOSE( 0xb5, 0x2561, 22)
#define BOX_DS_RTEE CHOOSE( 0xb6, 0x2562, 22)
#define BOX_DS_URCORNER CHOOSE( 0xb7, 0x2556, 12)
#define BOX_SD_URCORNER CHOOSE( 0xb8, 0x2555, 12)
#define BOX_D_RTEE CHOOSE( 0xb9, 0x2563, 22)
#define BOX_D_VLINE CHOOSE( 0xba, 0x2551, 25)
#define BOX_D_URCORNER CHOOSE( 0xbb, 0x2557, 12)
#define BOX_D_LRCORNER CHOOSE( 0xbc, 0x255D, 11)
#define BOX_DS_LRCORNER CHOOSE( 0xbd, 0x255c, 11)
#define BOX_SD_LRCORNER CHOOSE( 0xbe, 0x255b, 11)
#define BOX_URCORNER CHOOSE( 0xbf, 0x2510, 12)
#define BOX_LLCORNER CHOOSE( 0xc0, 0x2514, 14)
#define BOX_BTEE CHOOSE( 0xc1, 0x2534, 23)
#define BOX_TTEE CHOOSE( 0xc2, 0x252c, 24)
#define BOX_LTEE CHOOSE( 0xc3, 0x251c, 21)
#define BOX_HLINE CHOOSE( 0xc4, 0x2500, 18)
#define BOX_PLUS CHOOSE( 0xc5, 0x253c, 15)
#define BOX_SD_LTEE CHOOSE( 0xc6, 0x255e, 21)
#define BOX_DS_LTEE CHOOSE( 0xc7, 0x255f, 21)
#define BOX_D_LLCORNER CHOOSE( 0xc8, 0x255A, 14)
#define BOX_D_ULCORNER CHOOSE( 0xc9, 0x2554, 13)
#define BOX_D_BTEE CHOOSE( 0xca, 0x2569, 23)
#define BOX_D_TTEE CHOOSE( 0xcb, 0x2566, 24)
#define BOX_D_LTEE CHOOSE( 0xcc, 0x2560, 21)
#define BOX_D_HLINE CHOOSE( 0xcd, 0x2550, 18)
#define BOX_D_PLUS CHOOSE( 0xce, 0x256C, 15)
#define BOX_SD_BTEE CHOOSE( 0xcf, 0x2567, 23)
#define BOX_DS_BTEE CHOOSE( 0xd0, 0x2568, 23)
#define BOX_SD_TTEE CHOOSE( 0xd1, 0x2564, 24)
#define BOX_DS_TTEE CHOOSE( 0xd2, 0x2565, 24)
#define BOX_DS_LLCORNER CHOOSE( 0xd3, 0x2559, 14)
#define BOX_SD_LLCORNER CHOOSE( 0xd4, 0x2558, 14)
#define BOX_SD_ULCORNER CHOOSE( 0xd5, 0x2552, 13)
#define BOX_DS_ULCORNER CHOOSE( 0xd6, 0x2553, 13)
#define BOX_DS_PLUS CHOOSE( 0xd7, 0x256b, 15)
#define BOX_SD_PLUS CHOOSE( 0xd8, 0x256a, 15)
#define BOX_LRCORNER CHOOSE( 0xd9, 0x2518, 11)
#define BOX_ULCORNER CHOOSE( 0xda, 0x250c, 13)
#define FULL_BLOCK CHOOSE( 0xdb, 0x2588, 0)
#define LOWER_HALF_BLOCK CHOOSE( 0xdc, 0x2584, TBD)
#define LEFT_HALF_BLOCK CHOOSE( 0xdd, 0x258c, TBD)
#define RIGHT_HALF_BLOCK CHOOSE( 0xde, 0x2590, TBD)
#define UPPER_HALF_BLOCK CHOOSE( 0xdf, 0x2580, TBD)
#define ALPHA CHOOSE( 0xe0, 0x03b1, TBD)
#define BETA CHOOSE( 0xe1, 0x00df, TBD)
#define GAMMA CHOOSE( 0xe2, 0x0393, TBD)
#define PI CHOOSE( 0xe3, 0x03c0, 28)
#define UPPERCASE_SIGMA CHOOSE( 0xe4, 0x03a3, TBD)
#define LOWERCASE_SIGMA CHOOSE( 0xe5, 0x03c3, TBD)
#define MU CHOOSE( 0xe6, 0x00b5, 0xb5)
#define TAU CHOOSE( 0xe7, 0x03c4, TBD)
#define UPPERCASE_PHI CHOOSE( 0xe8, 0x03a6, TBD)
#define THETA CHOOSE( 0xe9, 0x0398, TBD)
#define OMEGA CHOOSE( 0xea, 0x03a9, TBD)
#define DELTA CHOOSE( 0xeb, 0x03b4, TBD)
#define INFINITY_SIGN CHOOSE( 0xec, 0x221e, TBD)
#define LOWERCASE_PHI CHOOSE( 0xed, 0x03c6, TBD)
#define EPSILON CHOOSE( 0xee, 0x03b5, TBD)
#define INTERSECTION CHOOSE( 0xef, 0x2229, TBD)
#define TRIPLE_BAR CHOOSE( 0xf0, 0x2261, TBD)
#define PLUS_OR_MINUS CHOOSE( 0xf1, 0x00b1, 8)
#define GREATER_THAN_OR_EQUAL_TO CHOOSE( 0xf2, 0x2265, 27)
#define LESSER_THAN_OR_EQUAL_TO CHOOSE( 0xf3, 0x2264, 26)
#define UPPER_HALF_INTEGRAL_SIGN CHOOSE( 0xf4, 0x2320, TBD)
#define LOWER_HALF_INTEGRAL_SIGN CHOOSE( 0xf5, 0x2321, TBD)
#define DIVISION_SIGN CHOOSE( 0xf6, 0x00f7, 0xf7)
#define APPROXIMATELY_EQUALS_SIGN CHOOSE( 0xf7, 0x2248, TBD)
#define DEGREE_SIGN CHOOSE( 0xf8, 0x00b0, 0xb0)
#define LARGE_BULLET CHOOSE( 0xf9, 0x2219, 7)
#define SMALL_BULLET CHOOSE( 0xfa, 0x00b7, 0xb7)
#define SQUARE_ROOT CHOOSE( 0xfb, 0x221a, TBD)
#define SUPERSCRIPT_N CHOOSE( 0xfc, 0x207f, TBD)
#define SUPERSCRIPT_2 CHOOSE( 0xfd, 0x00b2, 0xb2)
#define CENTERED_SQUARE CHOOSE( 0xfe, 0x25a0, TBD)
#define NON_BREAKING_SPACE CHOOSE( 0xff, 0x00a0, TBD)
/* It says at http://unicode.org/charts/PDF/U2300.pdf */
/* that '...the scan line numbers here refer to old, */
/* low-resolution technology for terminals, with only */
/* nine scan lines per fixed-size character glyph. */
/* Even-numbered scan lines are unified with box */
/* drawing graphics." */
/* The utility of these is questionable; they'd */
/* work Just Fine in wingdi (_if_ the appropriate */
/* glyphs are available), but not elsewhere. */
#define HORIZ_SCAN_LINE_1 CHOOSE( 0x2d, 0x23ba, 16)
#define HORIZ_SCAN_LINE_3 CHOOSE( 0x2d, 0x23bb, 17)
#define HORIZ_SCAN_LINE_7 CHOOSE( 0x2d, 0x23bc, 19)
#define HORIZ_SCAN_LINE_9 CHOOSE( '_', 0x23bd, 20)
/* Code page 437 lacks a 'for real' not-equals, so for that, */
/* we use the double-horizontal single-vertical box drawing : */
#define NOT_EQUALS_SIGN CHOOSE( 0xd8, 0x2260, 29)
# define A(x) ((chtype)x | A_ALTCHARSET)
chtype acs_map[128] =
{
A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8),
A(9), A(10),
CLUB, HEART, SPADE, SMILE, REV_SMILE, /* 11 12 13 14 15 */
MEDIUM_BULLET, WHITE_BULLET, PILCROW, SECTION_SIGN, /* 16 17 18 19 */
A_ORDINAL, O_ORDINAL, LOWERCASE_PHI, /* 20 21 22 */
INVERTED_EXCLAMATION_MARK, INVERTED_QUESTION_MARK, /* 23 24 */
REVERSED_NOT_SIGN, NOT_SIGN, /* 25 26 */
UPPER_HALF_INTEGRAL_SIGN, LOWER_HALF_INTEGRAL_SIGN, /* 27 28 */
SUPERSCRIPT_N, CENTERED_SQUARE, F_WITH_HOOK, /* 29 30 31 */
RIGHT_ARROW, LEFT_ARROW, UP_ARROW, DOWN_ARROW, /* 32 !"# */
PI, NOT_EQUALS_SIGN, VULGAR_HALF, VULGAR_QUARTER, /* $%&' */
'(',
LEFT_ANGLE_QUOTE_MARK, RIGHT_ANGLE_QUOTE_MARK, /* )* */
DARK_SHADE, SUPERSCRIPT_2, INFINITY_SIGN, /* +,- */
ALPHA, BETA, GAMMA, UPPERCASE_SIGMA, LOWERCASE_SIGMA, /* ./012 */
'3',
MU, TAU, UPPERCASE_PHI, THETA, OMEGA, DELTA, EPSILON, /* 456789: */
BOX_SD_LRCORNER, BOX_SD_URCORNER, BOX_SD_ULCORNER, /* ;<= */
BOX_SD_LLCORNER, BOX_SD_PLUS, /* >? */
BOX_SD_LTEE, BOX_SD_RTEE, BOX_SD_BTEE, BOX_SD_TTEE, /* @ABC */
BOX_D_LRCORNER, BOX_D_URCORNER, BOX_D_ULCORNER, /* DEF */
BOX_D_LLCORNER, BOX_D_PLUS, /* GH */
BOX_D_LTEE, BOX_D_RTEE, BOX_D_BTEE, BOX_D_TTEE, /* IJKL */
BOX_DS_LRCORNER, BOX_DS_URCORNER, BOX_DS_ULCORNER, /* MNO */
BOX_DS_LLCORNER, BOX_DS_PLUS, /* PQ */
BOX_DS_LTEE, BOX_DS_RTEE, BOX_DS_BTEE, BOX_DS_TTEE, /* RSTU */
BOX_LRCORNER, BOX_URCORNER, BOX_ULCORNER, /* VWX */
BOX_LLCORNER, BOX_PLUS, /* YZ */
BOX_LTEE, BOX_RTEE, BOX_BTEE, BOX_TTEE, /* [\]^ */
BOX_HLINE, BOX_VLINE, BOX_D_HLINE, BOX_D_VLINE, /* _`ab */
DIVISION_SIGN, APPROXIMATELY_EQUALS_SIGN, /* cd */
INTERSECTION, TRIPLE_BAR, /* ef */
SMALL_BULLET, LARGE_BULLET, SQUARE_ROOT, /* ghi */
DIAMOND, MEDIUM_SHADE, /* jk */
HORIZ_SCAN_LINE_1, HORIZ_SCAN_LINE_3, /* lm */
HORIZ_SCAN_LINE_7, HORIZ_SCAN_LINE_9, /* no */
UPPER_HALF_BLOCK, LOWER_HALF_BLOCK, /* pq */
LEFT_HALF_BLOCK, RIGHT_HALF_BLOCK, FULL_BLOCK, /* rst */
LESSER_THAN_OR_EQUAL_TO, GREATER_THAN_OR_EQUAL_TO, /* uv */
DEGREE_SIGN, PLUS_OR_MINUS, LIGHT_SHADE, SPLAT, /* wxyz */
CENT_SIGN, YEN_SIGN, PESETA_SIGN, STERLING_SIGN, /* {|}~ */
A(127)
};
# undef A

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,134 @@
/* Public Domain Curses */
/* Private definitions and declarations for use within PDCurses.
These should generally not be referenced by applications. */
#ifndef __CURSES_INTERNALS__
#define __CURSES_INTERNALS__ 1
#define CURSES_LIBRARY
#include <curses.h>
#if defined(__TURBOC__) || defined(__EMX__) || defined(__DJGPP__) || \
defined(__CYGWIN__) || defined(__MINGW32__) || \
defined(__WATCOMC__) || defined(__PACIFIC__)
# ifndef HAVE_VSSCANF
# define HAVE_VSSCANF /* have vsscanf() */
# endif
#endif
#if defined(__CYGWIN__) || defined(__MINGW32__) || \
defined(__LCC__) || defined(__WATCOMC__)
# ifndef HAVE_VSNPRINTF
# define HAVE_VSNPRINTF /* have vsnprintf() */
# endif
#endif
#if defined(_MSC_VER) && defined(_WIN32) && !defined(_CRT_SECURE_NO_DEPRECATE)
# define _CRT_SECURE_NO_DEPRECATE 1 /* kill nonsense warnings */
#endif
/*----------------------------------------------------------------------*/
typedef struct /* structure for ripped off lines */
{
int line;
int (*init)(WINDOW *, int);
} RIPPEDOFFLINE;
/* Window properties */
#define _SUBWIN 0x01 /* window is a subwindow */
#define _PAD 0x10 /* X/Open Pad. */
#define _SUBPAD 0x20 /* X/Open subpad. */
/* Miscellaneous */
#define _NO_CHANGE -1 /* flags line edge unchanged */
#define _ECHAR 0x08 /* Erase char (^H) */
#define _DWCHAR 0x17 /* Delete Word char (^W) */
#define _DLCHAR 0x15 /* Delete Line char (^U) */
extern WINDOW *pdc_lastscr;
extern FILE *pdc_dbfp; /* tracing file pointer (NULL = off) */
extern bool pdc_color_started;
extern unsigned long pdc_key_modifiers;
extern MOUSE_STATUS pdc_mouse_status;
/*----------------------------------------------------------------------*/
/* Platform implementation functions */
void PDC_beep(void);
bool PDC_can_change_color(void);
int PDC_color_content(short, short *, short *, short *);
bool PDC_check_key(void);
int PDC_curs_set(int);
void PDC_flushinp(void);
int PDC_get_columns(void);
int PDC_get_cursor_mode(void);
int PDC_get_key(void);
int PDC_get_rows(void);
void PDC_gotoyx(int, int);
int PDC_init_color(short, short, short, short);
void PDC_init_pair(short, short, short);
int PDC_modifiers_set(void);
int PDC_mouse_set(void);
void PDC_napms(int);
int PDC_pair_content(short, short *, short *);
void PDC_reset_prog_mode(void);
void PDC_reset_shell_mode(void);
int PDC_resize_screen(int, int);
void PDC_restore_screen_mode(int);
void PDC_save_screen_mode(int);
void PDC_scr_close(void);
void PDC_scr_free(void);
int PDC_scr_open(int, char **);
void PDC_set_keyboard_binary(bool);
void PDC_transform_line(int, int, int, const chtype *);
const char *PDC_sysname(void);
/* Internal cross-module functions */
void PDC_init_atrtab(void);
WINDOW *PDC_makelines(WINDOW *);
WINDOW *PDC_makenew(int, int, int, int);
int PDC_mouse_in_slk(int, int);
void PDC_slk_free(void);
void PDC_slk_initialize(void);
void PDC_sync(WINDOW *);
#ifdef PDC_WIDE
int PDC_mbtowc(wchar_t *, const char *, size_t);
size_t PDC_mbstowcs(wchar_t *, const char *, size_t);
size_t PDC_wcstombs(char *, const wchar_t *, size_t);
#endif
#ifdef PDCDEBUG
# define PDC_LOG(x) if (pdc_dbfp) PDC_debug x
#else
# define PDC_LOG(x)
#endif
/* Internal macros for attributes */
#ifdef CHTYPE_LONG
# define PDC_COLOR_PAIRS 256
#else
# define PDC_COLOR_PAIRS 32
#endif
#ifndef max
# define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
# define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#define DIVROUND(num, divisor) (((num) + ((divisor) >> 1)) / (divisor))
#define PDC_CLICK_PERIOD 150 /* time to wait for a click, if
not set by mouseinterval() */
#endif /* __CURSES_INTERNALS__*/

View File

@@ -0,0 +1,93 @@
/* $Id: getopt.h,v 1.1 2009/10/16 19:50:28 rodney Exp rodney $ */
/* $OpenBSD: getopt.h,v 1.1 2002/12/03 20:24:29 millert Exp $ */
/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Dieter Baron and Thomas Klausner.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _GETOPT_H_
#define _GETOPT_H_
#if 0
#include <sys/cdefs.h>
#endif
/*
* GNU-like getopt_long() and 4.4BSD getsubopt()/optreset extensions
*/
#define no_argument 0
#define required_argument 1
#define optional_argument 2
struct option {
/* name of long option */
const char *name;
/*
* one of no_argument, required_argument, and optional_argument:
* whether option takes an argument
*/
int has_arg;
/* if not NULL, set *flag to val when option found */
int *flag;
/* if flag not NULL, value to set *flag to; else return value */
int val;
};
#ifdef __cplusplus
extern "C" {
#endif
int getopt_long(int, char * const *, const char *,
const struct option *, int *);
int getopt_long_only(int, char * const *, const char *,
const struct option *, int *);
#ifndef _GETOPT_DEFINED
#define _GETOPT_DEFINED
int getopt(int, char * const *, const char *);
int getsubopt(char **, char * const *, char **);
extern char *optarg; /* getopt(3) external variables */
extern int opterr;
extern int optind;
extern int optopt;
extern int optreset;
extern char *suboptarg; /* getsubopt(3) external variable */
#endif /* _GETOPT_DEFINED */
#ifdef __cplusplus
}
#endif
#endif /* !_GETOPT_H_ */

View File

@@ -0,0 +1,56 @@
/* Public Domain Curses */
/*----------------------------------------------------------------------*
* Panels for PDCurses *
*----------------------------------------------------------------------*/
#ifndef __PDCURSES_PANEL_H__
#define __PDCURSES_PANEL_H__ 1
#include <curses.h>
#if defined(__cplusplus) || defined(__cplusplus__) || defined(__CPLUSPLUS)
extern "C"
{
#endif
typedef struct panelobs
{
struct panelobs *above;
struct panel *pan;
} PANELOBS;
typedef struct panel
{
WINDOW *win;
int wstarty;
int wendy;
int wstartx;
int wendx;
struct panel *below;
struct panel *above;
const void *user;
struct panelobs *obscure;
} PANEL;
PDCEX int bottom_panel(PANEL *pan);
PDCEX int del_panel(PANEL *pan);
PDCEX int hide_panel(PANEL *pan);
PDCEX int move_panel(PANEL *pan, int starty, int startx);
PDCEX PANEL *new_panel(WINDOW *win);
PDCEX PANEL *panel_above(const PANEL *pan);
PDCEX PANEL *panel_below(const PANEL *pan);
PDCEX int panel_hidden(const PANEL *pan);
PDCEX const void *panel_userptr(const PANEL *pan);
PDCEX WINDOW *panel_window(const PANEL *pan);
PDCEX int replace_panel(PANEL *pan, WINDOW *win);
PDCEX int set_panel_userptr(PANEL *pan, const void *uptr);
PDCEX int show_panel(PANEL *pan);
PDCEX int top_panel(PANEL *pan);
PDCEX void update_panels(void);
#if defined(__cplusplus) || defined(__cplusplus__) || defined(__CPLUSPLUS)
}
#endif
#endif /* __PDCURSES_PANEL_H__ */

View File

@@ -0,0 +1,48 @@
/* Public Domain Curses */
/* PDCurses doesn't operate with terminfo, but we need these functions for
compatibility, to allow some things (notably, interface libraries for
other languages) to be compiled. Anyone who tries to actually _use_
them will be disappointed, since they only return ERR. */
#ifndef __PDCURSES_TERM_H__
#define __PDCURSES_TERM_H__ 1
#include <curses.h>
#if defined(__cplusplus) || defined(__cplusplus__) || defined(__CPLUSPLUS)
extern "C"
{
#endif
typedef struct
{
const char *_termname;
} TERMINAL;
/* PDCEX is defined in curses.h */
PDCEX TERMINAL *cur_term;
int del_curterm(TERMINAL *);
int putp(const char *);
int restartterm(const char *, int, int *);
TERMINAL *set_curterm(TERMINAL *);
int setterm(const char *);
int setupterm(const char *, int, int *);
int tgetent(char *, const char *);
int tgetflag(const char *);
int tgetnum(const char *);
char *tgetstr(const char *, char **);
char *tgoto(const char *, int, int);
int tigetflag(const char *);
int tigetnum(const char *);
char *tigetstr(const char *);
char *tparm(const char *, long, long, long, long, long,
long, long, long, long);
int tputs(const char *, int, int (*)(int));
#if defined(__cplusplus) || defined(__cplusplus__) || defined(__CPLUSPLUS)
}
#endif
#endif /* __PDCURSES_TERM_H__ */

View File

@@ -0,0 +1,56 @@
#ifndef _UNISTD_H
#define _UNISTD_H 1
/* This is intended as a drop-in replacement for unistd.h on Windows.
* Please add functionality as neeeded.
* https://stackoverflow.com/a/826027/1202830
*/
#include <stdlib.h>
#include <io.h>
#include <getopt.h> /* getopt at: https://gist.github.com/ashelly/7776712 */
#include <process.h> /* for getpid() and the exec..() family */
#include <direct.h> /* for _getcwd() and _chdir() */
#define srandom srand
#define random rand
/* Values for the second argument to access.
These may be OR'd together. */
#define R_OK 4 /* Test for read permission. */
#define W_OK 2 /* Test for write permission. */
//#define X_OK 1 /* execute permission - unsupported in windows*/
#define F_OK 0 /* Test for existence. */
#define access _access
#define dup2 _dup2
#define execve _execve
#define ftruncate _chsize
#define unlink _unlink
#define fileno _fileno
#define getcwd _getcwd
#define chdir _chdir
#define isatty _isatty
#define lseek _lseek
/* read, write, and close are NOT being #defined here, because while there are file handle specific versions for Windows, they probably don't work for sockets. You need to look at your app and consider whether to call e.g. closesocket(). */
#ifdef _WIN64
#define ssize_t __int64
#else
#define ssize_t long
#endif
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
/* should be in some equivalent to <sys/types.h> */
typedef __int8 int8_t;
typedef __int16 int16_t;
typedef __int32 int32_t;
typedef __int64 int64_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
#endif /* unistd.h */

View File

@@ -169,16 +169,18 @@ CScript rogue_highlanderopret(uint8_t funcid,uint256 gametxid,int32_t regslot,CP
uint8_t rogue_highlanderopretdecode(uint256 &gametxid, uint256 &tokenid, int32_t &regslot, CPubKey &pk, std::vector<uint8_t> &playerdata, std::string &symbol, std::string &pname,CScript scriptPubKey)
{
std::string name, description; std::vector<uint8_t> vorigPubkey;
std::vector<std::pair<uint8_t, vscript_t>> oprets, opretsDummy;
std::vector<uint8_t> vopretNonfungible, vopret, vopretDummy,origpubkey;
uint8_t e, f,*script; std::vector<CPubKey> voutPubkeys;
tokenid = zeroid;
GetOpReturnData(scriptPubKey, vopret);
script = (uint8_t *)vopret.data();
if ( script[1] == 'c' && (f= DecodeTokenCreateOpRet(scriptPubKey,origpubkey,name,description,vopretNonfungible)) == 'c' )
if ( script[1] == 'c' && (f= DecodeTokenCreateOpRet(scriptPubKey,origpubkey,name,description, oprets)) == 'c' )
{
GetOpretBlob(oprets, OPRETID_NONFUNGIBLEDATA, vopretNonfungible);
vopret = vopretNonfungible;
}
else if ( script[1] != 'H' && script[1] != 'Q' && (f= DecodeTokenOpRet(scriptPubKey, e, tokenid, voutPubkeys, vopretDummy)) != 0 )
else if ( script[1] != 'H' && script[1] != 'Q' && (f= DecodeTokenOpRet(scriptPubKey, e, tokenid, voutPubkeys, opretsDummy)) != 0 )
{
//fprintf(stderr,"decode opret %c tokenid.%s\n",script[1],tokenid.GetHex().c_str());
GetNonfungibleData(tokenid, vopretNonfungible); //load nonfungible data from the 'tokenbase' tx
@@ -206,17 +208,20 @@ uint8_t rogue_keystrokesopretdecode(uint256 &gametxid,uint256 &batontxid,CPubKey
uint8_t rogue_registeropretdecode(uint256 &gametxid,uint256 &tokenid,uint256 &playertxid,CScript scriptPubKey)
{
std::string name, description; std::vector<uint8_t> vorigPubkey;
std::vector<std::pair<uint8_t, vscript_t>> oprets;
std::vector<uint8_t> vopretNonfungible, vopret, vopretDummy,origpubkey;
uint8_t e, f,*script; std::vector<CPubKey> voutPubkeys;
tokenid = zeroid;
GetOpReturnData(scriptPubKey, vopret);
script = (uint8_t *)vopret.data();
if ( script[1] == 'c' && (f= DecodeTokenCreateOpRet(scriptPubKey,origpubkey,name,description,vopretNonfungible)) == 'c' )
if ( script[1] == 'c' && (f= DecodeTokenCreateOpRet(scriptPubKey,origpubkey,name,description,oprets)) == 'c' )
{
GetOpretBlob(oprets, OPRETID_NONFUNGIBLEDATA, vopretNonfungible);
vopret = vopretNonfungible;
}
else if ( script[1] != 'R' && (f= DecodeTokenOpRet(scriptPubKey, e, tokenid, voutPubkeys, vopretDummy)) != 0 )
else if ( script[1] != 'R' && (f= DecodeTokenOpRet(scriptPubKey, e, tokenid, voutPubkeys, oprets)) != 0 )
{
GetOpretBlob(oprets, OPRETID_ROGUEGAMEDATA, vopretDummy); // blob from non-creation tx opret
vopret = vopretDummy;
}
if ( vopret.size() > 2 && E_UNMARSHAL(vopret,ss >> e; ss >> f; ss >> gametxid; ss >> playertxid) != 0 && e == EVAL_ROGUE && f == 'R' )
@@ -277,54 +282,6 @@ int32_t rogue_iamregistered(int32_t maxplayers,uint256 gametxid,CTransaction tx,
return(0);
}
int32_t rogue_playersalive(int32_t &numplayers,uint256 gametxid,int32_t maxplayers)
{
int32_t i,alive = 0; uint64_t txfee = 10000;
numplayers = 0;
for (i=0; i<maxplayers; i++)
{
if ( CCgettxout(gametxid,1+i,1) < 0 )
{
numplayers++;
if (CCgettxout(gametxid,1+maxplayers+i,1) == txfee )
alive++;
}
}
return(alive);
}
uint64_t rogue_gamefields(UniValue &obj,int64_t maxplayers,int64_t buyin,uint256 gametxid,char *myrogueaddr)
{
CBlockIndex *pindex; int32_t ht,delay,numplayers; uint256 hashBlock; uint64_t seed=0; char cmd[512]; CTransaction tx;
if ( myGetTransaction(gametxid,tx,hashBlock) != 0 && (pindex= komodo_blockindex(hashBlock)) != 0 )
{
ht = pindex->GetHeight();
delay = ROGUE_REGISTRATION * (maxplayers > 1);
obj.push_back(Pair("height",ht));
obj.push_back(Pair("start",ht+delay));
if ( komodo_nextheight() > ht+delay )
{
if ( (pindex= komodo_chainactive(ht+delay)) != 0 )
{
hashBlock = pindex->GetBlockHash();
obj.push_back(Pair("starthash",hashBlock.ToString()));
memcpy(&seed,&hashBlock,sizeof(seed));
seed &= (1LL << 62) - 1;
obj.push_back(Pair("seed",(int64_t)seed));
if ( rogue_iamregistered(maxplayers,gametxid,tx,myrogueaddr) > 0 )
sprintf(cmd,"cc/rogue/rogue %llu %s",(long long)seed,gametxid.ToString().c_str());
else sprintf(cmd,"./komodo-cli -ac_name=%s cclib register %d \"[%%22%s%%22]\"",ASSETCHAINS_SYMBOL,EVAL_ROGUE,gametxid.ToString().c_str());
obj.push_back(Pair("run",cmd));
}
}
}
obj.push_back(Pair("alive",rogue_playersalive(numplayers,gametxid,maxplayers)));
obj.push_back(Pair("numplayers",numplayers));
obj.push_back(Pair("maxplayers",maxplayers));
obj.push_back(Pair("buyin",ValueFromAmount(buyin)));
return(seed);
}
int32_t rogue_isvalidgame(struct CCcontract_info *cp,int32_t &gameheight,CTransaction &tx,int64_t &buyin,int32_t &maxplayers,uint256 txid,int32_t unspentv0)
{
uint256 hashBlock; int32_t i,numvouts; char coinaddr[64]; CPubKey roguepk; uint64_t txfee = 10000;
@@ -338,7 +295,7 @@ int32_t rogue_isvalidgame(struct CCcontract_info *cp,int32_t &gameheight,CTransa
txid = tx.GetHash();
//fprintf(stderr,"set txid %s %llu\n",txid.GetHex().c_str(),(long long)CCgettxout(txid,0,1));
}
if ( IsCClibvout(cp,tx,0,cp->unspendableCCaddr) == txfee && (unspentv0 == 0 || CCgettxout(txid,0,1) == txfee) )
if ( IsCClibvout(cp,tx,0,cp->unspendableCCaddr) == txfee && (unspentv0 == 0 || CCgettxout(txid,0,1,0) == txfee) )
{
if ( rogue_newgameopreturndecode(buyin,maxplayers,tx.vout[numvouts-1].scriptPubKey) == 'G' )
{
@@ -364,9 +321,29 @@ int32_t rogue_isvalidgame(struct CCcontract_info *cp,int32_t &gameheight,CTransa
} else return(-1);
}
UniValue rogue_playerobj(std::vector<uint8_t> playerdata,uint256 playertxid,uint256 tokenid,std::string symbol,std::string pname)
void disp_playerdata(std::vector<uint8_t> playerdata)
{
int32_t i; struct rogue_player P; char packitemstr[512],*datastr=0; UniValue obj(UniValue::VOBJ),a(UniValue::VARR);
struct rogue_player P; int32_t i; char packitemstr[512];
if ( playerdata.size() > 0 )
{
for (i=0; i<playerdata.size(); i++)
{
((uint8_t *)&P)[i] = playerdata[i];
fprintf(stderr,"%02x",playerdata[i]);
}
fprintf(stderr," <- playerdata: gold.%d hp.%d strength.%d/%d level.%d exp.%d dl.%d\n",P.gold,P.hitpoints,P.strength&0xffff,P.strength>>16,P.level,P.experience,P.dungeonlevel);
for (i=0; i<P.packsize&&i<MAXPACK; i++)
{
rogue_packitemstr(packitemstr,&P.roguepack[i]);
fprintf(stderr,"%d: %s\n",i,packitemstr);
}
fprintf(stderr,"\n");
}
}
UniValue rogue_playerobj(std::vector<uint8_t> playerdata,uint256 playertxid,uint256 tokenid,std::string symbol,std::string pname,uint256 gametxid)
{
int32_t i,vout,spentvini,numvouts,n=0; uint256 txid,spenttxid,hashBlock; struct rogue_player P; char packitemstr[512],*datastr=0; UniValue obj(UniValue::VOBJ),a(UniValue::VARR); CTransaction tx;
memset(&P,0,sizeof(P));
if ( playerdata.size() > 0 )
{
@@ -384,6 +361,37 @@ UniValue rogue_playerobj(std::vector<uint8_t> playerdata,uint256 playertxid,uint
rogue_packitemstr(packitemstr,&P.roguepack[i]);
a.push_back(packitemstr);
}
txid = playertxid;
vout = 1;
while ( CCgettxout(txid,vout,1,0) < 0 )
{
spenttxid = zeroid;
spentvini = -1;
if ( (spentvini= myIsutxo_spent(spenttxid,txid,vout)) >= 0 )
txid = spenttxid;
else if ( myIsutxo_spentinmempool(spenttxid,spentvini,txid,vout) == 0 || spenttxid == zeroid )
{
fprintf(stderr,"mempool tracking error %s/v0\n",txid.ToString().c_str());
break;
}
txid = spenttxid;
vout = 0;
if ( myGetTransaction(txid,tx,hashBlock) != 0 && (numvouts= tx.vout.size()) > 1 )
{
for (i=0; i<numvouts; i++)
if ( tx.vout[i].nValue == 1 )
{
vout = i;
break;
}
}
//fprintf(stderr,"trace spend to %s/v%d\n",txid.GetHex().c_str(),vout);
if ( n++ > ROGUE_MAXITERATIONS )
break;
}
obj.push_back(Pair("gametxid",gametxid.GetHex()));
if ( txid != playertxid )
obj.push_back(Pair("batontxid",txid.GetHex()));
obj.push_back(Pair("playertxid",playertxid.GetHex()));
if ( tokenid != zeroid )
obj.push_back(Pair("tokenid",tokenid.GetHex()));
@@ -447,6 +455,7 @@ int32_t rogue_playerdata(struct CCcontract_info *cp,uint256 &origplayergame,uint
{
if ( (f= rogue_highlanderopretdecode(gametxid,tokenid,regslot,pk,playerdata,symbol,pname,playertx.vout[numvouts-1].scriptPubKey)) == 'H' || f == 'Q' )
{
origplayergame = gametxid;
if ( tokenid != zeroid )
{
playertxid = tokenid;
@@ -472,19 +481,34 @@ int32_t rogue_playerdata(struct CCcontract_info *cp,uint256 &origplayergame,uint
int32_t rogue_playerdataspend(CMutableTransaction &mtx,uint256 playertxid,int32_t vout,uint256 origplayergame)
{
int64_t txfee = 10000;
if ( CCgettxout(playertxid,vout,1) == 1 ) // not sure if this is enough validation
int64_t txfee = 10000; CTransaction tx; uint256 hashBlock;
if ( CCgettxout(playertxid,vout,1,0) == 1 ) // not sure if this is enough validation
{
mtx.vin.push_back(CTxIn(playertxid,vout,CScript()));
return(0);
} else return(-1);
}
else
{
vout = 0;
if ( myGetTransaction(playertxid,tx,hashBlock) != 0 && tx.vout[vout].nValue == 1 && tx.vout[vout].scriptPubKey.IsPayToCryptoCondition() != 0 )
{
if ( CCgettxout(playertxid,vout,1,0) == 1 ) // not sure if this is enough validation
{
mtx.vin.push_back(CTxIn(playertxid,vout,CScript()));
return(0);
}
}
return(-1);
}
}
int32_t rogue_findbaton(struct CCcontract_info *cp,uint256 &playertxid,char **keystrokesp,int32_t &numkeys,int32_t &regslot,std::vector<uint8_t> &playerdata,uint256 &batontxid,int32_t &batonvout,int64_t &batonvalue,int32_t &batonht,uint256 gametxid,CTransaction gametx,int32_t maxplayers,char *destaddr,int32_t &numplayers,std::string &symbol,std::string &pname)
{
int32_t i,numvouts,spentvini,n,matches = 0; CPubKey pk; uint256 tid,active,spenttxid,tokenid,hashBlock,txid,origplayergame; CTransaction spenttx,matchtx,batontx; std::vector<uint8_t> checkdata; CBlockIndex *pindex; char ccaddr[64],*keystrokes=0;
numkeys = numplayers = 0;
playertxid = zeroid;
batonvalue = numkeys = numplayers = batonht = 0;
playertxid = batontxid = zeroid;
if ( keystrokesp != 0 )
*keystrokesp = 0;
for (i=0; i<maxplayers; i++)
{
//fprintf(stderr,"findbaton.%d of %d\n",i,maxplayers);
@@ -505,82 +529,172 @@ int32_t rogue_findbaton(struct CCcontract_info *cp,uint256 &playertxid,char **ke
}
if ( matches == 1 )
{
if ( myIsutxo_spent(spenttxid,gametxid,maxplayers+i+1) < 0 )
numvouts = matchtx.vout.size();
//fprintf(stderr,"matchtxid.%s matches.%d numvouts.%d\n",matchtx.GetHash().GetHex().c_str(),matches,numvouts);
if ( rogue_registeropretdecode(txid,tokenid,playertxid,matchtx.vout[numvouts-1].scriptPubKey) == 'R' )//&& txid == gametxid )
{
numvouts = matchtx.vout.size();
//fprintf(stderr,"matchtxid.%s matches.%d numvouts.%d\n",matchtx.GetHash().GetHex().c_str(),matches,numvouts);
if ( rogue_registeropretdecode(txid,tokenid,playertxid,matchtx.vout[numvouts-1].scriptPubKey) == 'R' )//&& txid == gametxid )
//fprintf(stderr,"tokenid.%s txid.%s vs gametxid.%s player.%s\n",tokenid.GetHex().c_str(),txid.GetHex().c_str(),gametxid.GetHex().c_str(),playertxid.GetHex().c_str());
if ( tokenid != zeroid )
active = tokenid;
else active = playertxid;
if ( active == zeroid || rogue_playerdata(cp,origplayergame,tid,pk,playerdata,symbol,pname,active) == 0 )
{
//fprintf(stderr,"tokenid.%s txid.%s vs gametxid.%s player.%s\n",tokenid.GetHex().c_str(),txid.GetHex().c_str(),gametxid.GetHex().c_str(),playertxid.GetHex().c_str());
if ( tokenid != zeroid )
active = tokenid;
else active = playertxid;
if ( active == zeroid || rogue_playerdata(cp,origplayergame,tid,pk,playerdata,symbol,pname,active) == 0 )
txid = matchtx.GetHash();
//fprintf(stderr,"scan forward active.%s spenttxid.%s\n",active.GetHex().c_str(),txid.GetHex().c_str());
n = 0;
while ( CCgettxout(txid,0,1,0) < 0 )
{
txid = matchtx.GetHash();
//fprintf(stderr,"scan forward active.%s spenttxid.%s\n",active.GetHex().c_str(),txid.GetHex().c_str());
n = 0;
while ( CCgettxout(txid,0,1) < 0 )
spenttxid = zeroid;
spentvini = -1;
if ( (spentvini= myIsutxo_spent(spenttxid,txid,0)) >= 0 )
txid = spenttxid;
else
{
spenttxid = zeroid;
spentvini = -1;
if ( (spentvini= myIsutxo_spent(spenttxid,txid,0)) >= 0 )
txid = spenttxid;
else if ( myIsutxo_spentinmempool(spenttxid,spentvini,txid,0) == 0 || spenttxid == zeroid )
if ( myIsutxo_spentinmempool(spenttxid,spentvini,txid,0) == 0 || spenttxid == zeroid )
{
fprintf(stderr,"mempool tracking error %s/v0\n",txid.ToString().c_str());
return(-2);
}
txid = spenttxid;
if ( spentvini != 0 )
return(-3);
if ( keystrokesp != 0 && myGetTransaction(spenttxid,spenttx,hashBlock) != 0 && spenttx.vout.size() >= 2 )
{
uint256 g,b; CPubKey p; std::vector<uint8_t> k;
if ( rogue_keystrokesopretdecode(g,b,p,k,spenttx.vout[spenttx.vout.size()-1].scriptPubKey) == 'K' )
{
keystrokes = (char *)realloc(keystrokes,numkeys + (int32_t)k.size());
for (i=0; i<k.size(); i++)
keystrokes[numkeys+i] = (char)k[i];
numkeys += (int32_t)k.size();
(*keystrokesp) = keystrokes;
}
}
if ( ++n >= ROGUE_MAXITERATIONS )
{
fprintf(stderr,"rogue_findbaton n.%d, seems something is wrong\n",n);
return(-5);
}
//fprintf(stderr,"n.%d txid.%s\n",n,txid.GetHex().c_str());
}
//fprintf(stderr,"set baton %s\n",txid.GetHex().c_str());
batontxid = txid;
batonvout = 0; // not vini
// how to detect timeout, bailedout, highlander
hashBlock = zeroid;
if ( myGetTransaction(batontxid,batontx,hashBlock) != 0 && batontx.vout.size() > 0 )
txid = spenttxid;
//fprintf(stderr,"n.%d next txid.%s/v%d\n",n,txid.GetHex().c_str(),spentvini);
if ( spentvini != 0 ) // game is over?
{
if ( hashBlock == zeroid )
batonht = komodo_nextheight();
else if ( (pindex= komodo_blockindex(hashBlock)) == 0 )
return(-4);
else batonht = pindex->GetHeight();
batonvalue = batontx.vout[0].nValue;
//printf("batonht.%d keystrokes[%d]\n",batonht,numkeys);
return(0);
} else fprintf(stderr,"couldnt find baton\n");
} else fprintf(stderr,"error with playerdata\n");
} else fprintf(stderr,"findbaton opret error\n");
}
else
{
fprintf(stderr,"already played\n");
return(-5);
}
}
if ( keystrokesp != 0 && myGetTransaction(spenttxid,spenttx,hashBlock) != 0 && spenttx.vout.size() >= 2 )
{
uint256 g,b; CPubKey p; std::vector<uint8_t> k;
if ( rogue_keystrokesopretdecode(g,b,p,k,spenttx.vout[spenttx.vout.size()-1].scriptPubKey) == 'K' )
{
keystrokes = (char *)realloc(keystrokes,numkeys + (int32_t)k.size());
for (i=0; i<k.size(); i++)
keystrokes[numkeys+i] = (char)k[i];
numkeys += (int32_t)k.size();
(*keystrokesp) = keystrokes;
//fprintf(stderr,"updated keystrokes.%p[%d]\n",keystrokes,numkeys);
}
}
//fprintf(stderr,"n.%d txid.%s\n",n,txid.GetHex().c_str());
if ( ++n >= ROGUE_MAXITERATIONS )
{
fprintf(stderr,"rogue_findbaton n.%d, seems something is wrong\n",n);
return(-5);
}
}
//fprintf(stderr,"set baton %s\n",txid.GetHex().c_str());
batontxid = txid;
batonvout = 0; // not vini
// how to detect timeout, bailedout, highlander
hashBlock = zeroid;
if ( myGetTransaction(batontxid,batontx,hashBlock) != 0 && batontx.vout.size() > 0 )
{
if ( hashBlock == zeroid )
batonht = komodo_nextheight();
else if ( (pindex= komodo_blockindex(hashBlock)) == 0 )
return(-4);
else batonht = pindex->GetHeight();
batonvalue = batontx.vout[0].nValue;
//printf("batonht.%d keystrokes[%d]\n",batonht,numkeys);
return(0);
} else fprintf(stderr,"couldnt find baton\n");
} else fprintf(stderr,"error with playerdata\n");
} else fprintf(stderr,"findbaton opret error\n");
}
return(-1);
}
int32_t rogue_playersalive(int32_t &openslots,int32_t &numplayers,uint256 gametxid,int32_t maxplayers,int32_t gameht,CTransaction gametx)
{
int32_t i,n,vout,spentvini,registration_open = 0,alive = 0; CTransaction tx; uint256 txid,spenttxid,hashBlock; CBlockIndex *pindex; uint64_t txfee = 10000;
numplayers = openslots = 0;
if ( komodo_nextheight() <= gameht+ROGUE_MAXKEYSTROKESGAP )
registration_open = 1;
for (i=0; i<maxplayers; i++)
{
//fprintf(stderr,"players alive %d of %d\n",i,maxplayers);
if ( CCgettxout(gametxid,1+i,1,0) < 0 )
{
numplayers++;
//fprintf(stderr,"players alive %d spent baton\n",i);
if ( CCgettxout(gametxid,1+maxplayers+i,1,0) == txfee )
{
txid = gametxid;
vout = 1+i;
//fprintf(stderr,"rogue_playersalive scan forward active.%s spenttxid.%s\n",gametxid.GetHex().c_str(),txid.GetHex().c_str());
n = 0;
while ( CCgettxout(txid,vout,1,0) < 0 )
{
spenttxid = zeroid;
spentvini = -1;
if ( (spentvini= myIsutxo_spent(spenttxid,txid,vout)) >= 0 )
txid = spenttxid;
else if ( myIsutxo_spentinmempool(spenttxid,spentvini,txid,vout) == 0 || spenttxid == zeroid )
{
fprintf(stderr,"mempool tracking error %s/v0\n",txid.ToString().c_str());
break;
}
txid = spenttxid;
vout = 0;
//fprintf(stderr,"n.%d next txid.%s/v%d\n",n,txid.GetHex().c_str(),spentvini);
if ( spentvini != 0 )
break;
if ( n++ > ROGUE_MAXITERATIONS )
break;
}
if ( txid != zeroid )
{
if ( myGetTransaction(txid,tx,hashBlock) != 0 )
{
if ( (pindex= komodo_blockindex(hashBlock)) != 0 )
{
if ( pindex->GetHeight() <= gameht+ROGUE_MAXKEYSTROKESGAP )
alive++;
}
}
}
}
}
else if ( registration_open != 0 )
openslots++;
}
//fprintf(stderr,"numalive.%d openslots.%d\n",alive,openslots);
return(alive);
}
uint64_t rogue_gamefields(UniValue &obj,int64_t maxplayers,int64_t buyin,uint256 gametxid,char *myrogueaddr)
{
CBlockIndex *pindex; int32_t ht,openslots,delay,numplayers; uint256 hashBlock; uint64_t seed=0; char cmd[512]; CTransaction tx;
if ( myGetTransaction(gametxid,tx,hashBlock) != 0 && (pindex= komodo_blockindex(hashBlock)) != 0 )
{
ht = pindex->GetHeight();
delay = ROGUE_REGISTRATION * (maxplayers > 1);
obj.push_back(Pair("height",ht));
obj.push_back(Pair("start",ht+delay));
if ( komodo_nextheight() > ht+delay )
{
if ( (pindex= komodo_chainactive(ht+delay)) != 0 )
{
hashBlock = pindex->GetBlockHash();
obj.push_back(Pair("starthash",hashBlock.ToString()));
memcpy(&seed,&hashBlock,sizeof(seed));
seed &= (1LL << 62) - 1;
obj.push_back(Pair("seed",(int64_t)seed));
if ( rogue_iamregistered(maxplayers,gametxid,tx,myrogueaddr) > 0 )
sprintf(cmd,"cc/rogue/rogue %llu %s",(long long)seed,gametxid.ToString().c_str());
else sprintf(cmd,"./komodo-cli -ac_name=%s cclib register %d \"[%%22%s%%22]\"",ASSETCHAINS_SYMBOL,EVAL_ROGUE,gametxid.ToString().c_str());
obj.push_back(Pair("run",cmd));
}
}
obj.push_back(Pair("alive",rogue_playersalive(openslots,numplayers,gametxid,maxplayers,ht,tx)));
obj.push_back(Pair("openslots",openslots));
obj.push_back(Pair("numplayers",numplayers));
}
obj.push_back(Pair("maxplayers",maxplayers));
obj.push_back(Pair("buyin",ValueFromAmount(buyin)));
return(seed);
}
void rogue_gameplayerinfo(struct CCcontract_info *cp,UniValue &obj,uint256 gametxid,CTransaction gametx,int32_t vout,int32_t maxplayers,char *myrogueaddr)
{
// identify if bailout or quit or timed out
@@ -594,7 +708,7 @@ void rogue_gameplayerinfo(struct CCcontract_info *cp,UniValue &obj,uint256 gamet
obj.push_back(Pair("slot",(int64_t)vout-1));
if ( (retval= rogue_findbaton(cp,playertxid,0,numkeys,regslot,playerdata,batontxid,batonvout,batonvalue,batonht,gametxid,gametx,maxplayers,destaddr,numplayers,symbol,pname)) == 0 )
{
if ( CCgettxout(gametxid,maxplayers+vout,1) == 10000 )
if ( CCgettxout(gametxid,maxplayers+vout,1,0) == 10000 )
{
if ( myGetTransaction(batontxid,batontx,hashBlock) != 0 && batontx.vout.size() > 1 )
{
@@ -611,7 +725,7 @@ void rogue_gameplayerinfo(struct CCcontract_info *cp,UniValue &obj,uint256 gamet
obj.push_back(Pair("batonvalue",ValueFromAmount(batonvalue)));
obj.push_back(Pair("batonht",(int64_t)batonht));
if ( playerdata.size() > 0 )
obj.push_back(Pair("player",rogue_playerobj(playerdata,playertxid,tokenid,symbol,pname)));
obj.push_back(Pair("player",rogue_playerobj(playerdata,playertxid,tokenid,symbol,pname,gametxid)));
} else fprintf(stderr,"findbaton err.%d\n",retval);
}
@@ -624,7 +738,7 @@ int64_t rogue_registrationbaton(CMutableTransaction &mtx,uint256 gametxid,CTrans
for (j=0; j<maxplayers; j++)
{
vout = ((r + j) % maxplayers) + 1;
if ( CCgettxout(gametxid,vout,1) == ROGUE_REGISTRATIONSIZE )
if ( CCgettxout(gametxid,vout,1,0) == ROGUE_REGISTRATIONSIZE )
{
mtx.vin.push_back(CTxIn(gametxid,vout,CScript()));
return(ROGUE_REGISTRATIONSIZE);
@@ -700,7 +814,7 @@ UniValue rogue_playerinfo(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
playertxid = juint256(jitem(params,0));
if ( rogue_playerdata(cp,origplayergame,tokenid,pk,playerdata,symbol,pname,playertxid) < 0 )
return(cclib_error(result,"invalid playerdata"));
result.push_back(Pair("player",rogue_playerobj(playerdata,playertxid,tokenid,symbol,pname)));
result.push_back(Pair("player",rogue_playerobj(playerdata,playertxid,tokenid,symbol,pname,origplayergame)));
} else return(cclib_error(result,"no playertxid"));
return(result);
} else return(cclib_error(result,"couldnt reparse params"));
@@ -764,20 +878,23 @@ UniValue rogue_register(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
CCaddr1of2set(cp,roguepk,roguepk,cp->CCpriv,destaddr);
mtx.vout.push_back(MakeTokensCC1vout(cp->evalcode, 1, burnpk));
std::vector<uint8_t> vopretExtra; uint8_t e, funcid; uint256 tid; std::vector<CPubKey> voutPubkeys, voutPubkeysEmpty; int32_t didtx = 0;
uint8_t e, funcid; uint256 tid; std::vector<CPubKey> voutPubkeys, voutPubkeysEmpty; int32_t didtx = 0;
CScript opretRegister = rogue_registeropret(gametxid, playertxid);
if ( playertxid != zeroid )
{
voutPubkeysEmpty.push_back(burnpk);
if ( myGetTransaction(playertxid,playertx,hashBlock) != 0 )
{
if ( (funcid= DecodeTokenOpRet(playertx.vout.back().scriptPubKey, e, tid, voutPubkeys, vopretExtra)) != 0)
std::vector<std::pair<uint8_t, vscript_t>> oprets;
if ( (funcid= DecodeTokenOpRet(playertx.vout.back().scriptPubKey, e, tid, voutPubkeys, oprets)) != 0)
{ // if token in the opret
didtx = 1;
if ( funcid == 'c' )
tid = tokenid == zeroid ? playertxid : tokenid;
vscript_t vopretRegister;
GetOpReturnData(opretRegister, vopretRegister);
rawtx = FinalizeCCTx(0, cp, mtx, mypk, txfee,
EncodeTokenOpRet(tid, voutPubkeysEmpty /*=never spent*/, opretRegister));
EncodeTokenOpRet(tid, voutPubkeysEmpty /*=never spent*/, std::make_pair(OPRETID_ROGUEGAMEDATA, vopretRegister)));
}
}
}
@@ -835,19 +952,20 @@ UniValue rogue_keystrokes(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
char *rogue_extractgame(int32_t makefiles,char *str,int32_t *numkeysp,std::vector<uint8_t> &newdata,uint64_t &seed,uint256 &playertxid,struct CCcontract_info *cp,uint256 gametxid,char *rogueaddr)
{
CPubKey roguepk; int32_t i,num,maxplayers,gameheight,batonht,batonvout,numplayers,regslot,numkeys,err; std::string symbol,pname; CTransaction gametx; int64_t buyin,batonvalue; char fname[64],*keystrokes = 0; std::vector<uint8_t> playerdata; uint256 batontxid; FILE *fp; uint8_t newplayer[10000]; struct rogue_player P,endP;
CPubKey roguepk; int32_t i,num,retval,maxplayers,gameheight,batonht,batonvout,numplayers,regslot,numkeys,err; std::string symbol,pname; CTransaction gametx; int64_t buyin,batonvalue; char fname[64],*keystrokes = 0; std::vector<uint8_t> playerdata; uint256 batontxid; FILE *fp; uint8_t newplayer[10000]; struct rogue_player P,endP;
roguepk = GetUnspendable(cp,0);
*numkeysp = 0;
seed = 0;
num = numkeys = 0;
playertxid = zeroid;
str[0] = 0;
if ( (err= rogue_isvalidgame(cp,gameheight,gametx,buyin,maxplayers,gametxid,0)) == 0 )
{
if ( rogue_findbaton(cp,playertxid,&keystrokes,numkeys,regslot,playerdata,batontxid,batonvout,batonvalue,batonht,gametxid,gametx,maxplayers,rogueaddr,numplayers,symbol,pname) == 0 )
if ( (retval= rogue_findbaton(cp,playertxid,&keystrokes,numkeys,regslot,playerdata,batontxid,batonvout,batonvalue,batonht,gametxid,gametx,maxplayers,rogueaddr,numplayers,symbol,pname)) == 0 )
{
UniValue obj;
seed = rogue_gamefields(obj,maxplayers,buyin,gametxid,rogueaddr);
//fprintf(stderr,"(%s) found baton %s numkeys.%d seed.%llu playerdata.%d playertxid.%s\n",pname.size()!=0?pname.c_str():Rogue_pname.c_str(),batontxid.ToString().c_str(),numkeys,(long long)seed,(int32_t)playerdata.size(),playertxid.GetHex().c_str());
//fprintf(stderr,"(%s) found baton %s numkeys.%d seed.%llu playerdata.%d playertxid.%s\n",pname.size()!=0?pname.c_str():Rogue_pname.c_str(),batontxid.ToString().c_str(),numkeys,(long long)seed,(int32_t)playerdata.size(),playertxid.GetHex().c_str());
memset(&P,0,sizeof(P));
if ( playerdata.size() > 0 )
{
@@ -873,6 +991,7 @@ char *rogue_extractgame(int32_t makefiles,char *str,int32_t *numkeysp,std::vecto
fclose(fp);
}
}
//fprintf(stderr,"call replay2\n");
num = rogue_replay2(newplayer,seed,keystrokes,numkeys,playerdata.size()==0?0:&P,0);
newdata.resize(num);
for (i=0; i<num; i++)
@@ -880,22 +999,26 @@ char *rogue_extractgame(int32_t makefiles,char *str,int32_t *numkeysp,std::vecto
newdata[i] = newplayer[i];
((uint8_t *)&endP)[i] = newplayer[i];
}
//fprintf(stderr,"back replay2 gold.%d\n",endP.gold);
if ( endP.gold <= 0 || endP.hitpoints <= 0 || (endP.strength&0xffff) <= 0 || endP.level <= 0 || endP.experience <= 0 || endP.dungeonlevel <= 0 )
{
//fprintf(stderr,"zero value character was killed -> no playerdata\n");
sprintf(str,"zero value character was killed -> no playerdata\n");
newdata.resize(0);
//P.gold = (P.gold * 8) / 10;
*numkeysp = numkeys;
return(keystrokes);
/* P.gold = (P.gold * 8) / 10;
if ( keystrokes != 0 )
{
free(keystrokes);
keystrokes = 0;
*numkeysp = 0;
}
return(keystrokes);
}*/
}
else
{
sprintf(str,"extracted $$$gold.%d hp.%d strength.%d/%d level.%d exp.%d dl.%d\n",endP.gold,endP.hitpoints,endP.strength&0xffff,endP.strength>>16,endP.level,endP.experience,endP.dungeonlevel);
fprintf(stderr,"%s\n",str);
sprintf(str,"$$$gold.%d hp.%d strength.%d/%d level.%d exp.%d dl.%d",endP.gold,endP.hitpoints,endP.strength&0xffff,endP.strength>>16,endP.level,endP.experience,endP.dungeonlevel);
//fprintf(stderr,"%s\n",str);
*numkeysp = numkeys;
return(keystrokes);
}
@@ -903,7 +1026,7 @@ char *rogue_extractgame(int32_t makefiles,char *str,int32_t *numkeysp,std::vecto
}
else
{
fprintf(stderr,"extractgame: couldnt find baton keystrokes.%p\n",keystrokes);
fprintf(stderr,"extractgame: couldnt find baton keystrokes.%p retval.%d\n",keystrokes,retval);
if ( keystrokes != 0 )
free(keystrokes), keystrokes = 0;
}
@@ -914,11 +1037,12 @@ char *rogue_extractgame(int32_t makefiles,char *str,int32_t *numkeysp,std::vecto
UniValue rogue_extract(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
UniValue result(UniValue::VOBJ); CPubKey pk,roguepk; int32_t i,n,numkeys,flag = 0; uint64_t seed; char str[512],rogueaddr[64],*pubstr,*keystrokes = 0; std::vector<uint8_t> newdata; uint256 gametxid,playertxid; FILE *fp; uint8_t pub33[33];
UniValue result(UniValue::VOBJ); CPubKey pk,roguepk; int32_t i,n,numkeys,flag = 0; uint64_t seed; char str[512],rogueaddr[64],*pubstr,*hexstr,*keystrokes = 0; std::vector<uint8_t> newdata; uint256 gametxid,playertxid; FILE *fp; uint8_t pub33[33];
pk = pubkey2pk(Mypubkey());
roguepk = GetUnspendable(cp,0);
result.push_back(Pair("name","rogue"));
result.push_back(Pair("method","extract"));
rogueaddr[0] = 0;
if ( params != 0 && (n= cJSON_GetArraySize(params)) > 0 )
{
if ( n > 0 )
@@ -927,23 +1051,35 @@ UniValue rogue_extract(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
result.push_back(Pair("gametxid",gametxid.GetHex()));
if ( n == 2 )
{
if ( (pubstr= jstr(jitem(params,1),0)) != 0 && strlen(pubstr) == 66 )
if ( (pubstr= jstr(jitem(params,1),0)) != 0 )
{
decode_hex(pub33,33,pubstr);
pk = buf2pk(pub33);
if (strlen(pubstr) == 66 )
{
decode_hex(pub33,33,pubstr);
pk = buf2pk(pub33);
}
else if ( strlen(pubstr) < 36 )
strcpy(rogueaddr,pubstr);
}
//fprintf(stderr,"gametxid.%s %s\n",gametxid.GetHex().c_str(),pubstr);
}
GetCCaddress1of2(cp,rogueaddr,roguepk,pk);
if ( rogueaddr[0] == 0 )
GetCCaddress1of2(cp,rogueaddr,roguepk,pk);
result.push_back(Pair("rogueaddr",rogueaddr));
str[0] = 0;
if ( (keystrokes= rogue_extractgame(1,str,&numkeys,newdata,seed,playertxid,cp,gametxid,rogueaddr)) != 0 )
{
result.push_back(Pair("status","success"));
flag = 1;
hexstr = (char *)malloc(numkeys*2 + 1);
for (i=0; i<numkeys; i++)
sprintf(&hexstr[i<<1],"%02x",keystrokes[i]);
hexstr[i<<1] = 0;
result.push_back(Pair("keystrokes",hexstr));
free(hexstr);
result.push_back(Pair("numkeys",(int64_t)numkeys));
result.push_back(Pair("playertxid",playertxid.GetHex()));
result.push_back(Pair("extracted",str));
result.push_back(Pair("numkeys",(int64_t)numkeys));
result.push_back(Pair("seed",(int64_t)seed));
sprintf(str,"cc/rogue/rogue %llu",(long long)seed);
result.push_back(Pair("replay",str));
@@ -956,36 +1092,59 @@ UniValue rogue_extract(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
return(result);
}
int32_t rogue_playerdata_validate(uint256 &playertxid,struct CCcontract_info *cp,std::vector<uint8_t> playerdata,uint256 gametxid,CPubKey pk)
int32_t rogue_playerdata_validate(int64_t *cashoutp,uint256 &playertxid,struct CCcontract_info *cp,std::vector<uint8_t> playerdata,uint256 gametxid,CPubKey pk)
{
static uint32_t good,bad; static uint256 prevgame;
char str[512],*keystrokes,rogueaddr[64],str2[67]; int32_t i,numkeys; std::vector<uint8_t> newdata; uint64_t seed; CPubKey roguepk; struct rogue_player P;
if ( gametxid == prevgame )
return(0);
prevgame = gametxid;
char str[512],*keystrokes,rogueaddr[64],str2[67],fname[64]; int32_t i,dungeonlevel,numkeys; std::vector<uint8_t> newdata; uint64_t seed,mult = 10; CPubKey roguepk; struct rogue_player P;
*cashoutp = 0;
roguepk = GetUnspendable(cp,0);
GetCCaddress1of2(cp,rogueaddr,roguepk,pk);
//fprintf(stderr,"call extractgame\n");
if ( (keystrokes= rogue_extractgame(0,str,&numkeys,newdata,seed,playertxid,cp,gametxid,rogueaddr)) != 0 )
{
//fprintf(stderr,"numkeys.%d rogue_extractgame %s\n",numkeys,gametxid.GetHex().c_str());
free(keystrokes);
//fprintf(stderr,"extracted.(%s)\n",str);
sprintf(fname,"rogue.%llu.pack",(long long)seed);
remove(fname);
for (i=0; i<newdata.size(); i++)
((uint8_t *)&P)[i] = newdata[i];
if ( P.amulet != 0 )
mult *= 5;
dungeonlevel = P.dungeonlevel;
if ( P.amulet != 0 && dungeonlevel < 26 )
dungeonlevel = 26;
*cashoutp = (uint64_t)P.gold * P.gold * mult * dungeonlevel;
if ( newdata == playerdata )
{
good++;
fprintf(stderr,"%s good.%d bad.%d\n",gametxid.GetHex().c_str(),good,bad);
if ( gametxid != prevgame )
{
prevgame = gametxid;
good++;
fprintf(stderr,"%s good.%d bad.%d\n",gametxid.GetHex().c_str(),good,bad);
}
return(0);
}
newdata[10] = newdata[11] = playerdata[10] = playerdata[11] = 0;
if ( newdata == playerdata )
{
good++;
fprintf(stderr,"%s matched after clearing maxstrength good.%d bad.%d\n",gametxid.GetHex().c_str(),good,bad);
if ( gametxid != prevgame )
{
prevgame = gametxid;
good++;
fprintf(stderr,"%s matched after clearing maxstrength good.%d bad.%d\n",gametxid.GetHex().c_str(),good,bad);
}
return(0);
}
newdata[0] = newdata[1] = playerdata[0] = playerdata[1] = 0; // vout.2 check will validate gold
if ( newdata == playerdata )
{
if ( gametxid != prevgame )
{
prevgame = gametxid;
good++;
fprintf(stderr,"%s matched after clearing lower 16bits of gold good.%d bad.%d\n",gametxid.GetHex().c_str(),good,bad);
}
return(0);
}
for (i=0; i<playerdata.size(); i++)
((uint8_t *)&P)[i] = playerdata[i];
if ( P.gold <= 0 || P.hitpoints <= 0 || (P.strength&0xffff) <= 0 || P.level <= 0 || P.experience <= 0 || P.dungeonlevel <= 0 )
{
//P.gold = (P.gold * 8) / 10;
@@ -993,16 +1152,29 @@ int32_t rogue_playerdata_validate(uint256 &playertxid,struct CCcontract_info *cp
// playerdata[i] = ((uint8_t *)&P)[i];
if ( newdata.size() == 0 )
{
good++;
if ( gametxid != prevgame )
{
prevgame = gametxid;
good++;
fprintf(stderr,"zero value character was killed -> no playerdata, good.%d bad.%d\n",good,bad);
}
*cashoutp = 0;
return(0);
}
fprintf(stderr,"zero value character was killed -> no playerdata, good.%d bad.%d\n",good,bad);
}
bad++;
fprintf(stderr,"%s playerdata: gold.%d hp.%d strength.%d/%d level.%d exp.%d dl.%d\n",gametxid.GetHex().c_str(),P.gold,P.hitpoints,P.strength&0xffff,P.strength>>16,P.level,P.experience,P.dungeonlevel);
fprintf(stderr,"newdata[%d] != playerdata[%d], numkeys.%d %s pub.%s playertxid.%s good.%d bad.%d\n",(int32_t)newdata.size(),(int32_t)playerdata.size(),numkeys,rogueaddr,pubkey33_str(str2,(uint8_t *)&pk),playertxid.GetHex().c_str(),good,bad);
if ( gametxid != prevgame )
{
prevgame = gametxid;
bad++;
disp_playerdata(newdata);
disp_playerdata(playerdata);
fprintf(stderr,"%s playerdata: gold.%d hp.%d strength.%d/%d level.%d exp.%d dl.%d\n",gametxid.GetHex().c_str(),P.gold,P.hitpoints,P.strength&0xffff,P.strength>>16,P.level,P.experience,P.dungeonlevel);
fprintf(stderr,"newdata[%d] != playerdata[%d], numkeys.%d %s pub.%s playertxid.%s good.%d bad.%d\n",(int32_t)newdata.size(),(int32_t)playerdata.size(),numkeys,rogueaddr,pubkey33_str(str2,(uint8_t *)&pk),playertxid.GetHex().c_str(),good,bad);
}
}
//fprintf(stderr,"no keys rogue_extractgame %s\n",gametxid.GetHex().c_str());
sprintf(fname,"rogue.%llu.pack",(long long)seed);
remove(fname);
//fprintf(stderr,"no keys rogue_extractgame %s\n",gametxid.GetHex().c_str());
return(-1);
}
@@ -1020,7 +1192,7 @@ UniValue rogue_finishgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
// vout0 -> 1% ingame gold
// get any playerdata, get all keystrokes, replay game and compare final state
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), komodo_nextheight());
UniValue result(UniValue::VOBJ); std::string rawtx,symbol,pname; CTransaction gametx; uint64_t seed,mult; int64_t buyin,batonvalue,inputsum,cashout,CCchange=0; int32_t i,err,gameheight,tmp,numplayers,regslot,n,num,dungeonlevel,numkeys,maxplayers,batonht,batonvout; char myrogueaddr[64],*keystrokes = 0; std::vector<uint8_t> playerdata,newdata,nodata; uint256 batontxid,playertxid,gametxid; CPubKey mypk,roguepk; uint8_t player[10000],mypriv[32],funcid;
UniValue result(UniValue::VOBJ); std::string rawtx,symbol,pname; CTransaction gametx; uint64_t seed,mult; int64_t buyin,batonvalue,inputsum,cashout=0,CCchange=0; int32_t i,err,gameheight,tmp,numplayers,regslot,n,num,dungeonlevel,numkeys,maxplayers,batonht,batonvout; char myrogueaddr[64],*keystrokes = 0; std::vector<uint8_t> playerdata,newdata,nodata; uint256 batontxid,playertxid,gametxid; CPubKey mypk,roguepk; uint8_t player[10000],mypriv[32],funcid;
struct CCcontract_info *cpTokens, tokensC;
if ( txfee == 0 )
@@ -1086,33 +1258,38 @@ UniValue rogue_finishgame(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
}
else
{
//if ( maxplayers == 1 )
// mult /= 2;
cpTokens = CCinit(&tokensC, EVAL_TOKENS);
mtx.vout.push_back(MakeCC1vout(EVAL_TOKENS, txfee, GetUnspendable(cpTokens,NULL))); // marker to token cc addr, burnable and validated
mtx.vout.push_back(MakeTokensCC1vout(cp->evalcode,1,mypk));
if ( P.amulet != 0 )
mult *= 5;
dungeonlevel = P.dungeonlevel;
if ( P.amulet != 0 && dungeonlevel < 21 )
dungeonlevel = 21;
if ( P.amulet != 0 && dungeonlevel < 26 )
dungeonlevel = 26;
cashout = (uint64_t)P.gold * P.gold * mult * dungeonlevel;
fprintf(stderr,"\nextracted $$$gold.%d -> %.8f ROGUE hp.%d strength.%d/%d level.%d exp.%d dl.%d n.%d amulet.%d\n",P.gold,(double)cashout/COIN,P.hitpoints,P.strength&0xffff,P.strength>>16,P.level,P.experience,P.dungeonlevel,n,P.amulet);
if ( funcid == 'H' && maxplayers > 1 )
{
if ( (numplayers != maxplayers || (numplayers - rogue_playersalive(tmp,gametxid,maxplayers)) > 1) && P.amulet == 0 )
return(cclib_error(result,"highlander must be a winner or last one standing"));
if ( P.amulet == 0 )
{
if ( numplayers != maxplayers )
return(cclib_error(result,"numplayers != maxplayers"));
else if ( rogue_playersalive(tmp,tmp,gametxid,maxplayers,gameheight,gametx) > 1 )
return(cclib_error(result,"highlander must be a winner or last one standing"));
}
cashout += numplayers * buyin;
}
if ( cashout >= txfee )
if ( cashout > 0 )
{
if ( (inputsum= AddCClibInputs(cp,mtx,roguepk,cashout,16,cp->unspendableCCaddr)) > (uint64_t)P.gold*mult )
if ( (inputsum= AddCClibInputs(cp,mtx,roguepk,cashout,60,cp->unspendableCCaddr)) > cashout )
CCchange = (inputsum - cashout);
mtx.vout.push_back(CTxOut(cashout,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
else fprintf(stderr,"couldnt find enough utxos\n");
}
mtx.vout.push_back(CTxOut(cashout,CScript() << ParseHex(HexStr(mypk)) << OP_CHECKSIG));
}
}
mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange + (batonvalue-3*txfee),roguepk));
if ( CCchange + (batonvalue-3*txfee) >= txfee )
mtx.vout.push_back(MakeCC1vout(cp->evalcode,CCchange + (batonvalue-3*txfee),roguepk));
Myprivkey(mypriv);
CCaddr1of2set(cp,roguepk,mypk,mypriv,myrogueaddr);
CScript opret;
@@ -1154,7 +1331,7 @@ UniValue rogue_highlander(uint64_t txfee,struct CCcontract_info *cp,cJSON *param
UniValue rogue_gameinfo(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
UniValue result(UniValue::VOBJ),a(UniValue::VARR); int32_t i,n,gameheight,maxplayers,numvouts; uint256 txid; CTransaction tx; int64_t buyin; uint64_t seed; bits256 t; char myrogueaddr[64]; CPubKey mypk,roguepk;
UniValue result(UniValue::VOBJ),a(UniValue::VARR); int32_t i,n,gameheight,maxplayers,numvouts; uint256 txid; CTransaction tx; int64_t buyin; uint64_t seed; bits256 t; char myrogueaddr[64],str[64]; CPubKey mypk,roguepk;
result.push_back(Pair("name","rogue"));
result.push_back(Pair("method","gameinfo"));
if ( params != 0 && (n= cJSON_GetArraySize(params)) > 0 )
@@ -1175,12 +1352,17 @@ UniValue rogue_gameinfo(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
result.push_back(Pair("seed",(int64_t)seed));
for (i=0; i<maxplayers; i++)
{
if ( CCgettxout(txid,i+1,1) < 0 )
if ( CCgettxout(txid,i+1,1,0) < 0 )
{
UniValue obj(UniValue::VOBJ);
rogue_gameplayerinfo(cp,obj,txid,tx,i+1,maxplayers,myrogueaddr);
a.push_back(obj);
}
else if ( 0 )
{
sprintf(str,"vout %d+1 is unspent",i);
result.push_back(Pair("unspent",str));
}
}
result.push_back(Pair("players",a));
} else return(cclib_error(result,"couldnt find valid game"));
@@ -1191,7 +1373,7 @@ UniValue rogue_gameinfo(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
UniValue rogue_pending(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
UniValue result(UniValue::VOBJ),a(UniValue::VARR); int64_t buyin; uint256 txid,hashBlock; CTransaction tx; int32_t maxplayers,numplayers,gameheight,nextheight,vout,numvouts; CPubKey roguepk; char coinaddr[64];
UniValue result(UniValue::VOBJ),a(UniValue::VARR); int64_t buyin; uint256 txid,hashBlock; CTransaction tx; int32_t openslots,maxplayers,numplayers,gameheight,nextheight,vout,numvouts; CPubKey roguepk; char coinaddr[64];
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue> > unspentOutputs;
roguepk = GetUnspendable(cp,0);
GetCCaddress(cp,coinaddr,roguepk);
@@ -1206,8 +1388,8 @@ UniValue rogue_pending(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
continue;
if ( rogue_isvalidgame(cp,gameheight,tx,buyin,maxplayers,txid,1) == 0 && nextheight <= gameheight+ROGUE_MAXKEYSTROKESGAP )
{
rogue_playersalive(numplayers,txid,maxplayers);
if ( numplayers < maxplayers )
rogue_playersalive(openslots,numplayers,txid,maxplayers,gameheight,tx);
if ( openslots > 0 )
a.push_back(txid.GetHex());
}
}
@@ -1270,7 +1452,7 @@ UniValue rogue_games(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
{
if ( rogue_isvalidgame(cp,gameheight,gametx,buyin,maxplayers,gametxid,0) == 0 )
{
if ( CCgettxout(txid,vout,1) < 0 )
if ( CCgettxout(txid,vout,1,0) < 0 )
b.push_back(gametxid.GetHex());
else a.push_back(gametxid.GetHex());
}
@@ -1308,11 +1490,19 @@ UniValue rogue_setname(uint64_t txfee,struct CCcontract_info *cp,cJSON *params)
bool rogue_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const CTransaction tx)
{
CScript scriptPubKey; std::vector<uint8_t> vopret; uint8_t *script,e,f,funcid; int32_t i,maxplayers,decoded=0,regslot,ind,err,dispflag,gameheight,score,numvouts; CTransaction vintx,gametx; CPubKey pk; uint256 hashBlock,gametxid,tokenid,batontxid,playertxid,ptxid; int64_t buyin; std::vector<uint8_t> playerdata,keystrokes; std::string symbol,pname;
if ( strcmp(ASSETCHAINS_SYMBOL,"ROGUE") == 0 && height < 21274 )
return(true);
CScript scriptPubKey; std::vector<uint8_t> vopret; uint8_t *script,e,f,funcid,tokentx=0; int32_t i,maxplayers,enabled = 0,decoded=0,regslot,ind,err,dispflag,gameheight,score,numvouts; CTransaction vintx,gametx; CPubKey pk; uint256 hashBlock,gametxid,txid,tokenid,batontxid,playertxid,ptxid; int64_t buyin,cashout; std::vector<uint8_t> playerdata,keystrokes; std::string symbol,pname;
if ( strcmp(ASSETCHAINS_SYMBOL,"ROGUE") == 0 )
{
if (height < 21274 )
return(true);
else if ( height > 50000 )
enabled = 1;
} else enabled = 1;
if ( (numvouts= tx.vout.size()) > 1 )
{
txid = tx.GetHash();
if ( txid == Parseuint256("1ae04dc0c5f2fca2053819a3a1b2efe5d355c34f58d6f16d59e5e2573e7baf7f") ) // osx rogue chain ht.50902
enabled = 0;
scriptPubKey = tx.vout[numvouts-1].scriptPubKey;
GetOpReturnData(scriptPubKey,vopret);
if ( vopret.size() > 2 )
@@ -1321,6 +1511,7 @@ bool rogue_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const C
funcid = script[1];
if ( (e= script[0]) == EVAL_TOKENS )
{
tokentx = funcid;
if ( (funcid= rogue_highlanderopretdecode(gametxid,tokenid,regslot,pk,playerdata,symbol,pname,scriptPubKey)) == 0 )
{
if ( (funcid= rogue_registeropretdecode(gametxid,tokenid,playertxid,scriptPubKey)) == 0 )
@@ -1351,9 +1542,7 @@ bool rogue_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const C
case 'R':
if ( (funcid= rogue_registeropretdecode(gametxid,tokenid,playertxid,scriptPubKey)) != 'R' )
{
//fprintf(stderr,"height.%d couldnt decode register opret\n",height);
//if ( height > 20000 )
return eval->Invalid("couldnt decode register opret");
return eval->Invalid("couldnt decode register opret");
}
// baton is created
// validation is done below
@@ -1361,22 +1550,13 @@ bool rogue_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const C
case 'K':
if ( (funcid= rogue_keystrokesopretdecode(gametxid,batontxid,pk,keystrokes,scriptPubKey)) != 'K' )
{
//fprintf(stderr,"height.%d couldnt decode keystrokes opret\n",height);
//if ( height > 20000 )
return eval->Invalid("couldnt decode keystrokes opret");
return eval->Invalid("couldnt decode keystrokes opret");
}
// spending the baton proves it is the user if the pk is the signer
return(true);
break;
case 'H': case 'Q':
if ( (f= rogue_highlanderopretdecode(gametxid,tokenid,regslot,pk,playerdata,symbol,pname,scriptPubKey)) != funcid )
{
//fprintf(stderr,"height.%d couldnt decode H/Q opret\n",height);
//if ( height > 20000 )
return eval->Invalid("couldnt decode H/Q opret");
}
// spending the baton proves it is the user if the pk is the signer
// rest of validation is done below
// done in the next switch statement as there are some H/Q tx with playerdata which would skip this section
break;
default:
return eval->Invalid("illegal rogue non-decoded funcid");
@@ -1390,13 +1570,40 @@ bool rogue_validate(struct CCcontract_info *cp,int32_t height,Eval *eval,const C
return(true);
case 'H': // win
case 'Q': // bailout
// verify pk belongs to this tx
if ( playerdata.size() > 0 )
if ( (f= rogue_highlanderopretdecode(gametxid,tokenid,regslot,pk,playerdata,symbol,pname,scriptPubKey)) != funcid )
{
if ( rogue_playerdata_validate(ptxid,cp,playerdata,gametxid,pk) < 0 )
//fprintf(stderr,"height.%d couldnt decode H/Q opret\n",height);
//if ( height > 20000 )
return eval->Invalid("couldnt decode H/Q opret");
}
// verify pk belongs to this tx
if ( tokentx == 'c' )
{
if ( playerdata.size() > 0 )
{
//fprintf(stderr,"ht.%d gametxid.%s player.%s invalid playerdata[%d]\n",height,gametxid.GetHex().c_str(),ptxid.GetHex().c_str(),(int32_t)playerdata.size());
} //else fprintf(stderr,"ht.%d playertxid.%s validated\n",height,ptxid.GetHex().c_str());
static char laststr[512]; char cashstr[512];
if ( rogue_playerdata_validate(&cashout,ptxid,cp,playerdata,gametxid,pk) < 0 )
{
sprintf(cashstr,"tokentx.(%c) decoded.%d ht.%d gametxid.%s player.%s invalid playerdata[%d]\n",tokentx,decoded,height,gametxid.GetHex().c_str(),ptxid.GetHex().c_str(),(int32_t)playerdata.size());
if ( strcmp(laststr,cashstr) != 0 )
{
strcpy(laststr,cashstr);
fprintf(stderr,"%s\n",cashstr);
}
if ( enabled != 0 )
return eval->Invalid("mismatched playerdata");
}
if ( funcid == 'H' )
cashout *= 2;
sprintf(cashstr,"tokentx.(%c) decoded.%d ht.%d txid.%s %.8f vs vout2 %.8f",tokentx,decoded,height,txid.GetHex().c_str(),(double)cashout/COIN,(double)tx.vout[2].nValue/COIN);
if ( strcmp(laststr,cashstr) != 0 )
{
strcpy(laststr,cashstr);
fprintf(stderr,"%s\n",cashstr);
}
} else cashout = 10000;
if ( enabled != 0 && tx.vout[2].nValue > cashout )
return eval->Invalid("mismatched cashout amount");
}
if ( funcid == 'Q' )
{

View File

@@ -2859,7 +2859,7 @@ UniValue sudoku_solution(uint64_t txfee,struct CCcontract_info *cp,cJSON *params
decode_hex((uint8_t *)&txid,32,txidstr);
txid = revuint256(txid);
result.push_back(Pair("txid",txid.GetHex()));
if ( CCgettxout(txid,0,1) < 0 )
if ( CCgettxout(txid,0,1,0) < 0 )
result.push_back(Pair("error","already solved"));
else if ( GetTransaction(txid,tx,hashBlock,false) != 0 && (numvouts= tx.vout.size()) > 1 )
{

2411
src/cc/tetris.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -289,15 +289,22 @@ void *chainparams_commandline(void *ptr)
mainParams.pchMessageStart[2] = (ASSETCHAINS_MAGIC >> 16) & 0xff;
mainParams.pchMessageStart[3] = (ASSETCHAINS_MAGIC >> 24) & 0xff;
fprintf(stderr,">>>>>>>>>> %s: p2p.%u rpc.%u magic.%08x %u %u coins\n",ASSETCHAINS_SYMBOL,ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,ASSETCHAINS_MAGIC,ASSETCHAINS_MAGIC,(uint32_t)ASSETCHAINS_SUPPLY);
if (ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH)
if (ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH)
{
// this is only good for 60 second blocks with an averaging window of 45. for other parameters, use:
// nLwmaAjustedWeight = (N+1)/2 * (0.9989^(500/nPowAveragingWindow)) * nPowTargetSpacing
// nLwmaAjustedWeight = (N+1)/2 * (0.9989^(500/nPowAveragingWindow)) * nPowTargetSpacing
mainParams.consensus.nLwmaAjustedWeight = 1350;
mainParams.consensus.nPowAveragingWindow = 45;
mainParams.consensus.powAlternate = uint256S("00000f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f");
}
else if (ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASHV1_1)
{
// this is only good for 60 second blocks with an averaging window of 45. for other parameters, use:
// nLwmaAjustedWeight = (N+1)/2 * (0.9989^(500/nPowAveragingWindow)) * nPowTargetSpacing
mainParams.consensus.nLwmaAjustedWeight = 1350;
mainParams.consensus.nPowAveragingWindow = 45;
mainParams.consensus.powAlternate = uint256S("0000000f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f");
}
if (ASSETCHAINS_LWMAPOS != 0)
{
@@ -668,7 +675,7 @@ public:
BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K));
nEquihashN = N;
nEquihashK = K;
genesis = CreateGenesisBlock(
1296688602,
uint256S("0x0000000000000000000000000000000000000000000000000000000000000009"),

View File

@@ -20,6 +20,7 @@
#include "clientversion.h"
#include "tinyformat.h"
#include "util.h"
#include <string>
@@ -34,7 +35,7 @@
* for both bitcoind and bitcoin-core, to make it harder for attackers to
* target servers or GUI users specifically.
*/
const std::string CLIENT_NAME("MagicBean");
const std::string CLIENT_NAME = GetArg("-ac_clientname", "MagicBean");
/**
* Client version number

View File

@@ -446,7 +446,7 @@ class CCoinsViewCache;
/**
* A reference to a mutable cache entry. Encapsulating it allows us to run
* cleanup code after the modification is finished, and keeping track of
* concurrent modifications.
* concurrent modifications.
*/
class CCoinsModifier
{
@@ -503,7 +503,7 @@ protected:
/**
* Make mutable so that we can "fill the cache" even from Get-methods
* declared as "const".
* declared as "const".
*/
mutable uint256 hashBlock;
mutable CCoinsMap cacheCoins;

View File

@@ -66,7 +66,7 @@ uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeigh
int seenOwnNotarisations = 0;
bool txscl = IsTXSCL(symbol);
int authority = GetSymbolAuthority(symbol);
for (int i=0; i<NOTARISATION_SCAN_LIMIT_BLOCKS; i++) {
if (i > kmdHeight) break;
@@ -90,13 +90,20 @@ uint256 CalculateProofRoot(const char* symbol, uint32_t targetCCid, int kmdHeigh
if (seenOwnNotarisations == 1) {
BOOST_FOREACH(Notarisation& nota, notarisations) {
if (IsTXSCL(nota.second.symbol) == txscl)
if (nota.second.ccId == targetCCid)
moms.push_back(nota.second.MoM);
if (GetSymbolAuthority(nota.second.symbol) == authority)
if (nota.second.ccId == targetCCid) {
moms.push_back(nota.second.MoM);
//fprintf(stderr, "added mom: %s\n",nota.second.MoM.GetHex().data());
}
}
}
}
// Not enough own notarisations found to return determinate MoMoM
destNotarisationTxid = uint256();
moms.clear();
return uint256();
end:
return GetMerkleRoot(moms);
}

View File

@@ -18,6 +18,18 @@
#include "cc/eval.h"
const int CROSSCHAIN_KOMODO = 1;
const int CROSSCHAIN_TXSCL = 2;
const int CROSSCHAIN_STAKED = 3;
typedef struct CrosschainAuthority {
uint8_t notaries[64][33];
int8_t size;
int8_t requiredSigs;
} CrosschainAuthority;
int GetSymbolAuthority(const char* symbol);
bool CheckTxAuthority(const CTransaction &tx, CrosschainAuthority auth);
/* On assetchain */
TxProof GetAssetchainProof(uint256 hash,CTransaction burnTx);

View File

@@ -0,0 +1,70 @@
#include "cc/eval.h"
#include "crosschain.h"
#include "notarisationdb.h"
#include "notaries_staked.h"
int GetSymbolAuthority(const char* symbol)
{
if (strncmp(symbol, "TXSCL", 5) == 0)
return CROSSCHAIN_TXSCL;
if (is_STAKED(symbol) != 0) {
//printf("RETURNED CROSSCHAIN STAKED AS TRUE\n");
return CROSSCHAIN_STAKED;
}
//printf("RETURNED CROSSCHAIN KOMODO AS TRUE\n");
return CROSSCHAIN_KOMODO;
}
bool CheckTxAuthority(const CTransaction &tx, CrosschainAuthority auth)
{
EvalRef eval;
if (tx.vin.size() < auth.requiredSigs) return false;
uint8_t seen[64] = {0};
BOOST_FOREACH(const CTxIn &txIn, tx.vin)
{
// Get notary pubkey
CTransaction tx;
uint256 hashBlock;
if (!eval->GetTxUnconfirmed(txIn.prevout.hash, tx, hashBlock)) return false;
if (tx.vout.size() < txIn.prevout.n) return false;
CScript spk = tx.vout[txIn.prevout.n].scriptPubKey;
if (spk.size() != 35) return false;
const unsigned char *pk = &spk[0];
if (pk++[0] != 33) return false;
if (pk[33] != OP_CHECKSIG) return false;
// Check it's a notary
for (int i=0; i<auth.size; i++) {
if (!seen[i]) {
if (memcmp(pk, auth.notaries[i], 33) == 0) {
seen[i] = 1;
goto found;
} else {
//printf("notary.%i is not valid!\n",i);
}
}
}
return false;
found:;
}
return true;
}
/*
const CrosschainAuthority auth_STAKED = [&](){
CrosschainAuthority auth;
auth.requiredSigs = (num_notaries_STAKED / 5);
auth.size = num_notaries_STAKED;
for (int n=0; n<auth.size; n++)
for (size_t i=0; i<33; i++)
sscanf(notaries_STAKED[n][1]+(i*2), "%2hhx", auth.notaries[n]+i);
return auth;
}();
*/

3
src/fiat/ilien Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/bash
./komodo-cli -ac_name=ILN $1 $2 $3 $4 $5 $6

2
src/fiat/iln Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/bash
./komodo-cli -ac_name=ILN $1 $2 $3 $4 $5 $6

Some files were not shown because too many files have changed in this diff Show More