Compare commits

...

20 Commits

Author SHA1 Message Date
s_nakamoto
cb420a1dfc run as daemon without GUI,
hooked wxApp::Initialize to ignore gtk-init-check failure if no GUI,
fork to daemonize,
rpc getinfo, getconnectioncount, getbalance, getgenerate, setgenerate,
-- version 0.2.6

git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@70 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-02-23 22:01:39 +00:00
s_nakamoto
0184604aaf transaction filter tabs instead of view->show generated
-- version 0.2.5

git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@69 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-02-21 21:42:01 +00:00
s_nakamoto
75199de534 Address Book with tabs instead of separate Your Address book,
with live update of default address in main window, 
New... button on main window for creating new receiving address, 
made receiving address labels more visible, 
ask user before paying transaction fee, 
when sending to bitcoin address also use a bitcoin address for the change, 
added some event.Skip() to fix UI glitches 
-- version 0.2.4

git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@68 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-02-20 21:59:59 +00:00
s_nakamoto
c6ab3cf6d9 safer wxGetTranslation wrapper
git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@67 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-02-17 23:55:43 +00:00
s_nakamoto
e480659765 all builds are now with wxWidgets-2.9.0, we are now using UTF-8,
added support for language translation file locale/<lang>/LC_MESSAGES/bitcoin.mo 
-- version 0.2.2

git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@66 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-02-17 17:22:01 +00:00
s_nakamoto
2b63e68bbf fix mingw makefile to use correct wxWidgets include,
this is the last version of makefile and makefile.vc for wxWidgets-2.8

git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@65 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-02-15 20:36:55 +00:00
s_nakamoto
5253d1ab77 strip out unfinished product, review and market stuff,
enable _() instead of wxT() in uiproject.fbp so it uses wxGetTranslation for the wxFormBuilder generated part of the UI

git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@64 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-02-15 04:03:07 +00:00
s_nakamoto
64a474a49b renamed a few rpc methods
git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@63 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-02-14 22:27:13 +00:00
s_nakamoto
c4319e678f Workaround for bug on wxWidgets 2.9.0 Ubuntu 9.10 64-bit where first character of the hidden columns were displayed so status column had three numbers overprinted. Fixed by adding a leading space to the hidden columns. 64-bit compile with wxWidgets 2.9.0 seems to be fully working normally now.
git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@62 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-02-14 00:08:27 +00:00
s_nakamoto
c85dfb148a updated build-unix.txt
git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@61 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-02-13 02:09:07 +00:00
s_nakamoto
98500d70a8 command line and JSON-RPC first draft, requires Boost 1.35 or higher for boost::asio,
added SetBitcoinAddress and GetBitcoinAddress methods on CScript, 
critsect interlocks around mapAddressBook, 
added some random delays in tx broadcast to improve privacy, 
now compiles with MSVC 8.0

git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@60 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-02-12 20:38:44 +00:00
s_nakamoto
fa9dbd6b62 better error message in check_type(), tell the types by name instead of by number
git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@59 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-02-10 19:46:04 +00:00
s_nakamoto
75990a46a7 JSON Spirit library from http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx, MIT license
git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@58 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-02-10 19:41:22 +00:00
s_nakamoto
c41226d847 revert revision 56, going in different direction with boost::asio and JSON-RPC
git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@57 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-02-10 19:33:04 +00:00
sirius-m
082e725b33 Added some basic IPC functionality using wxServer, wxClient and wxConnection.
Added the -blockamount command line option for an example of usage.


git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@56 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-02-04 15:31:46 +00:00
s_nakamoto
53d508072b update fSpent flag on wallet transactions if they're seen spent in case copy of wallet.dat was used elsewhere or restored from backup,
better error dialog box if try to spend already spent coins, 
got rid of unused notebook with only one tab on main dialog, 
nicer looking About dialog, 
resize About dialog better on linux

git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@55 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-02-03 22:58:40 +00:00
s_nakamoto
8be979d9ae now compiles on 64-bit Ubuntu Karmic with wxWidgets-2.9.0,
fixes for wxWidgets-2.9.0, 
added superfluous GetEventHandler()'s, 
there's still a bug on wx2.9.0 that the status number is mashed up for some reason otherwise seems to run fine

git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@54 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-01-28 21:49:20 +00:00
s_nakamoto
cb0f89646f simplify AddAddress,
readcompactsize limit, 
fixed a 64-bit compile error in serialize.h, 
change status "# blocks" to "# confirmations" and widen the column.

git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@53 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2010-01-28 00:31:00 +00:00
s_nakamoto
9a36562347 command line switch -noui
git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@52 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2009-12-17 23:16:27 +00:00
s_nakamoto
312c2c42b6 a few header changes for freebsd from madhatter
git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@51 1a98c847-1fd6-4fd8-948a-caf3550aa51b
2009-12-17 18:15:50 +00:00
46 changed files with 6043 additions and 10377 deletions

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2009 Satoshi Nakamoto
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
@@ -64,12 +64,6 @@ public:
}
}
explicit CBigNum(const std::string& str)
{
BN_init(this);
SetHex(str);
}
CBigNum& operator=(const CBigNum& b)
{
if (!BN_copy(this, &b))
@@ -309,6 +303,37 @@ public:
*this = 0 - *this;
}
std::string ToString(int nBase=10) const
{
CAutoBN_CTX pctx;
CBigNum bnBase = nBase;
CBigNum bn0 = 0;
string str;
CBigNum bn = *this;
BN_set_negative(&bn, false);
CBigNum dv;
CBigNum rem;
if (BN_cmp(&bn, &bn0) == 0)
return "0";
while (BN_cmp(&bn, &bn0) > 0)
{
if (!BN_div(&dv, &rem, &bn, &bnBase, pctx))
throw bignum_error("CBigNum::ToString() : BN_div failed");
bn = dv;
unsigned int c = rem.getulong();
str += "0123456789abcdef"[c];
}
if (BN_is_negative(this))
str += "-";
reverse(str.begin(), str.end());
return str;
}
std::string GetHex() const
{
return ToString(16);
}
unsigned int GetSerializeSize(int nType=0, int nVersion=VERSION) const
{
return ::GetSerializeSize(getvch(), nType, nVersion);
@@ -376,6 +401,7 @@ public:
CBigNum& operator>>=(unsigned int shift)
{
// Note: BN_rshift segfaults on 64-bit ubuntu 9.10 if 2^shift is greater than the number
if (!BN_rshift(this, this, shift))
throw bignum_error("CBigNum:operator>>= : BN_rshift failed");
return *this;
@@ -485,6 +511,7 @@ inline const CBigNum operator<<(const CBigNum& a, unsigned int shift)
inline const CBigNum operator>>(const CBigNum& a, unsigned int shift)
{
CBigNum r;
// Note: BN_rshift segfaults on 64-bit ubuntu 9.10 if 2^shift is greater than the number
if (!BN_rshift(&r, &a, shift))
throw bignum_error("CBigNum:operator>> : BN_rshift failed");
return r;

View File

@@ -1,6 +1,6 @@
Bitcoin v0.2.0 BETA
Copyright (c) 2009 Satoshi Nakamoto
Copyright (c) 2009-2010 Satoshi Nakamoto
Distributed under the MIT/X11 software license, see the accompanying
file license.txt or http://www.opensource.org/licenses/mit-license.php.
This product includes software developed by the OpenSSL Project for use in
@@ -13,20 +13,27 @@ WINDOWS BUILD NOTES
Compilers Supported
-------------------
MinGW GCC
Microsoft Visual C++ 6.0 SP6
MinGW GCC (recommended)
MSVC 6.0 SP6: You'll need Boost version 1.34 because they dropped support
for MSVC 6.0 after that. However, they didn't add Asio until 1.35.
You should still be able to build with MSVC 6.0 by adding Asio to 1.34 by
unpacking boost_asio_*.zip into the boost directory:
http://sourceforge.net/projects/asio/files/asio
MSVC 8.0 (2005) SP1 has been tested. Note: MSVC 7.0 and up have a habit of
linking to runtime DLLs that are not installed on XP by default.
Dependencies
------------
Libraries you need to download separately and build:
default path download
wxWidgets \wxwidgets http://www.wxwidgets.org/downloads/
or prebuilt: http://wxpack.sourceforge.net
OpenSSL \openssl http://www.openssl.org/source/
Berkeley DB \db http://www.oracle.com/technology/software/products/berkeley-db/index.html
Boost \boost http://www.boost.org/users/download/
default path download
wxWidgets-2.9 \wxwidgets http://www.wxwidgets.org/downloads/
OpenSSL \openssl http://www.openssl.org/source/
Berkeley DB \db http://www.oracle.com/technology/software/products/berkeley-db/index.html
Boost \boost http://www.boost.org/users/download/
Their licenses:
wxWidgets LGPL 2.1 with very liberal exceptions
@@ -36,10 +43,10 @@ Boost MIT-like license
Versions used in this release:
MinGW GCC 3.4.5
wxWidgets 2.8.9
wxWidgets 2.9.0
OpenSSL 0.9.8k
Berkeley DB 4.7.25.NC
Boost 1.34.1
Boost 1.42.1
Notes
@@ -52,6 +59,14 @@ The release is built with GCC and then "strip bitcoin.exe" to strip the debug
symbols, which reduces the executable size by about 90%.
wxWidgets
---------
cd \wxwidgets\build\msw
make -f makefile.gcc
or
nmake -f makefile.vc
OpenSSL
-------
Bitcoin does not use any encryption. If you want to do a no-everything
@@ -89,3 +104,13 @@ Using MinGW and MSYS:
cd \db\build_unix
sh ../dist/configure --enable-mingw --enable-cxx
make
Boost
-----
download bjam.exe from
http://sourceforge.net/project/showfiles.php?group_id=7586&package_id=72941
cd \boost
bjam toolset=gcc --build-type=complete stage
or
bjam toolset=msvc --build-type=complete stage

View File

@@ -1,6 +1,6 @@
Bitcoin v0.2.0 BETA
Copyright (c) 2009 Satoshi Nakamoto
Copyright (c) 2009-2010 Satoshi Nakamoto
Distributed under the MIT/X11 software license, see the accompanying
file license.txt or http://www.opensource.org/licenses/mit-license.php.
This product includes software developed by the OpenSSL Project for use in
@@ -13,15 +13,22 @@ UNIX BUILD NOTES
Dependencies
------------
apt-get install build-essential
apt-get install libgtk2.0-dev
apt-get install libssl-dev
apt-get install libdb4.7-dev
apt-get install libdb4.7++-dev
apt-get install libboost-dev
sudo apt-get install build-essential
sudo apt-get install libgtk2.0-dev
sudo apt-get install libssl-dev
sudo apt-get install libdb4.7-dev
sudo apt-get install libdb4.7++-dev
sudo apt-get install libboost-dev
We're now using wxWidgets 2.9, which uses UTF-8.
There isn't currently a debian package of wxWidgets we can use. The 2.8
packages for Karmic are UTF-16 unicode and won't work for us, and we've had
trouble building 2.8 on 64-bit.
You need to download wxWidgets from http://www.wxwidgets.org/downloads/
and build it yourself.
and build it yourself. See the build instructions and configure parameters
below.
Licenses of statically linked libraries:
wxWidgets LGPL 2.1 with very liberal exceptions
@@ -31,9 +38,9 @@ Boost MIT-like license
Versions used in this release:
GCC 4.3.3
OpenSSL 0.9.8k
wxWidgets 2.8.9
wxWidgets 2.9.0
Berkeley DB 4.7.25.NC
Boost 1.40.0
Boost 1.38.0
Notes
@@ -48,12 +55,14 @@ symbols, which reduces the executable size by about 90%.
wxWidgets
---------
cd /usr/local/wxWidgets-2.8.9
cd /usr/local
tar -xzvf wxWidgets-2.9.0.tar.gz
cd /usr/local/wxWidgets-2.9.0
mkdir buildgtk
cd buildgtk
../configure --with-gtk --enable-debug --disable-shared --enable-monolithic
make
su
sudo su
make install
ldconfig
@@ -61,7 +70,7 @@ ldconfig
Boost
-----
If you want to build Boost yourself,
cd /usr/local/boost_1_40_0
cd /usr/local/boost_1_38_0
su
./bootstrap.sh
./bjam install

40
db.cpp
View File

@@ -1,4 +1,4 @@
// Copyright (c) 2009 Satoshi Nakamoto
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
@@ -134,8 +134,6 @@ void CDB::Close()
CRITICAL_BLOCK(cs_db)
--mapFileUseCount[strFile];
RandAddSeed();
}
void CloseDb(const string& strFile)
@@ -456,7 +454,7 @@ bool CAddrDB::LoadAddresses()
CAddress addr(psz, NODE_NETWORK);
addr.nTime = 0; // so it won't relay unless successfully connected
if (addr.IsValid())
AddAddress(*this, addr);
AddAddress(addr);
}
}
catch (...) { }
@@ -509,27 +507,6 @@ bool LoadAddresses()
//
// CReviewDB
//
bool CReviewDB::ReadReviews(uint256 hash, vector<CReview>& vReviews)
{
vReviews.size(); // msvc workaround, just need to do anything with vReviews
return Read(make_pair(string("reviews"), hash), vReviews);
}
bool CReviewDB::WriteReviews(uint256 hash, const vector<CReview>& vReviews)
{
return Write(make_pair(string("reviews"), hash), vReviews);
}
//
// CWalletDB
//
@@ -595,14 +572,17 @@ bool CWalletDB::LoadWallet(vector<unsigned char>& vchDefaultKeyRet)
// wtx.hashBlock.ToString().substr(0,16).c_str(),
// wtx.mapValue["message"].c_str());
}
else if (strType == "key")
else if (strType == "key" || strType == "wkey")
{
vector<unsigned char> vchPubKey;
ssKey >> vchPubKey;
CPrivKey vchPrivKey;
ssValue >> vchPrivKey;
CWalletKey wkey;
if (strType == "key")
ssValue >> wkey.vchPrivKey;
else
ssValue >> wkey;
mapKeys[vchPubKey] = vchPrivKey;
mapKeys[vchPubKey] = wkey.vchPrivKey;
mapPubKeys[Hash160(vchPubKey)] = vchPubKey;
}
else if (strType == "defaultkey")
@@ -619,7 +599,6 @@ bool CWalletDB::LoadWallet(vector<unsigned char>& vchDefaultKeyRet)
ssKey >> strKey;
// Menu state
if (strKey == "fShowGenerated") ssValue >> fShowGenerated;
if (strKey == "fGenerateBitcoins") ssValue >> fGenerateBitcoins;
// Options
@@ -638,7 +617,6 @@ bool CWalletDB::LoadWallet(vector<unsigned char>& vchDefaultKeyRet)
}
printf("nFileVersion = %d\n", nFileVersion);
printf("fShowGenerated = %d\n", fShowGenerated);
printf("fGenerateBitcoins = %d\n", fGenerateBitcoins);
printf("nTransactionFee = %"PRI64d"\n", nTransactionFee);
printf("addrIncoming = %s\n", addrIncoming.ToString().c_str());

49
db.h
View File

@@ -1,8 +1,7 @@
// Copyright (c) 2009 Satoshi Nakamoto
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
#include <db_cxx.h>
class CTransaction;
class CTxIndex;
class CDiskBlockIndex;
@@ -14,6 +13,7 @@ class CAddress;
class CWalletTx;
extern map<string, string> mapAddressBook;
extern CCriticalSection cs_mapAddressBook;
extern bool fClient;
@@ -285,45 +285,6 @@ public:
class CReviewDB : public CDB
{
public:
CReviewDB(const char* pszMode="r+") : CDB("reviews.dat", pszMode) { }
private:
CReviewDB(const CReviewDB&);
void operator=(const CReviewDB&);
public:
bool ReadUser(uint256 hash, CUser& user)
{
return Read(make_pair(string("user"), hash), user);
}
bool WriteUser(uint256 hash, const CUser& user)
{
return Write(make_pair(string("user"), hash), user);
}
bool ReadReviews(uint256 hash, vector<CReview>& vReviews);
bool WriteReviews(uint256 hash, const vector<CReview>& vReviews);
};
class CMarketDB : public CDB
{
public:
CMarketDB(const char* pszMode="r+") : CDB("market.dat", pszMode) { }
private:
CMarketDB(const CMarketDB&);
void operator=(const CMarketDB&);
};
class CAddrDB : public CDB
{
public:
@@ -359,15 +320,17 @@ public:
bool WriteName(const string& strAddress, const string& strName)
{
CRITICAL_BLOCK(cs_mapAddressBook)
mapAddressBook[strAddress] = strName;
nWalletDBUpdated++;
mapAddressBook[strAddress] = strName;
return Write(make_pair(string("name"), strAddress), strName);
}
bool EraseName(const string& strAddress)
{
CRITICAL_BLOCK(cs_mapAddressBook)
mapAddressBook.erase(strAddress);
nWalletDBUpdated++;
mapAddressBook.erase(strAddress);
return Erase(make_pair(string("name"), strAddress));
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2009 Satoshi Nakamoto
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
@@ -29,15 +29,15 @@
#include <openssl/rand.h>
#include <openssl/sha.h>
#include <openssl/ripemd.h>
#include <db_cxx.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
#include <float.h>
#include <assert.h>
#include <malloc.h>
#include <memory>
#define BOUNDSCHECK 1
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
@@ -55,6 +55,8 @@
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
#ifdef __WXMSW__
#include <windows.h>
@@ -64,6 +66,7 @@
#include <shlwapi.h>
#include <io.h>
#include <process.h>
#include <malloc.h>
#else
#include <sys/time.h>
#include <sys/resource.h>
@@ -74,16 +77,16 @@
#include <errno.h>
#include <net/if.h>
#include <ifaddrs.h>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
#endif
#ifdef __BSD__
#include <netinet/in.h>
#endif
#pragma hdrstop
using namespace std;
using namespace boost;
#include "strlcpy.h"
#include "serialize.h"
#include "uint256.h"
@@ -96,7 +99,7 @@ using namespace boost;
#include "net.h"
#include "irc.h"
#include "main.h"
#include "market.h"
#include "rpc.h"
#include "uibase.h"
#include "ui.h"
@@ -110,3 +113,4 @@ using namespace boost;
#include "xpm/send16.xpm"
#include "xpm/send16noshadow.xpm"
#include "xpm/send20.xpm"
#include "xpm/about.xpm"

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2009 Satoshi Nakamoto
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
@@ -265,8 +265,7 @@ void ThreadIRCSeed(void* parg)
if (DecodeAddress(pszName, addr))
{
addr.nTime = GetAdjustedTime() - 51 * 60;
CAddrDB addrdb;
if (AddAddress(addrdb, addr))
if (AddAddress(addr))
printf("IRC got new address\n");
nGotIRCAddresses++;
}

6
irc.h
View File

@@ -1,8 +1,8 @@
// Copyright (c) 2009 Satoshi Nakamoto
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
extern bool RecvLine(SOCKET hSocket, string& strLine);
extern void ThreadIRCSeed(void* parg);
bool RecvLine(SOCKET hSocket, string& strLine);
void ThreadIRCSeed(void* parg);
extern int nGotIRCAddresses;

24
json/LICENSE.txt Normal file
View File

@@ -0,0 +1,24 @@
The MIT License
Copyright (c) 2007 - 2009 John W. Wilkinson
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

18
json/json_spirit.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef JSON_SPIRIT
#define JSON_SPIRIT
// Copyright John W. Wilkinson 2007 - 2009.
// Distributed under the MIT License, see accompanying file LICENSE.txt
// json spirit version 4.03
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include "json_spirit_value.h"
#include "json_spirit_reader.h"
#include "json_spirit_writer.h"
#include "json_spirit_utils.h"
#endif

View File

@@ -0,0 +1,54 @@
#ifndef JSON_SPIRIT_ERROR_POSITION
#define JSON_SPIRIT_ERROR_POSITION
// Copyright John W. Wilkinson 2007 - 2009.
// Distributed under the MIT License, see accompanying file LICENSE.txt
// json spirit version 4.03
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <string>
namespace json_spirit
{
// An Error_position exception is thrown by the "read_or_throw" functions below on finding an error.
// Note the "read_or_throw" functions are around 3 times slower than the standard functions "read"
// functions that return a bool.
//
struct Error_position
{
Error_position();
Error_position( unsigned int line, unsigned int column, const std::string& reason );
bool operator==( const Error_position& lhs ) const;
unsigned int line_;
unsigned int column_;
std::string reason_;
};
inline Error_position::Error_position()
: line_( 0 )
, column_( 0 )
{
}
inline Error_position::Error_position( unsigned int line, unsigned int column, const std::string& reason )
: line_( line )
, column_( column )
, reason_( reason )
{
}
inline bool Error_position::operator==( const Error_position& lhs ) const
{
if( this == &lhs ) return true;
return ( reason_ == lhs.reason_ ) &&
( line_ == lhs.line_ ) &&
( column_ == lhs.column_ );
}
}
#endif

137
json/json_spirit_reader.cpp Normal file
View File

@@ -0,0 +1,137 @@
// Copyright John W. Wilkinson 2007 - 2009.
// Distributed under the MIT License, see accompanying file LICENSE.txt
// json spirit version 4.03
#include "json_spirit_reader.h"
#include "json_spirit_reader_template.h"
using namespace json_spirit;
bool json_spirit::read( const std::string& s, Value& value )
{
return read_string( s, value );
}
void json_spirit::read_or_throw( const std::string& s, Value& value )
{
read_string_or_throw( s, value );
}
bool json_spirit::read( std::istream& is, Value& value )
{
return read_stream( is, value );
}
void json_spirit::read_or_throw( std::istream& is, Value& value )
{
read_stream_or_throw( is, value );
}
bool json_spirit::read( std::string::const_iterator& begin, std::string::const_iterator end, Value& value )
{
return read_range( begin, end, value );
}
void json_spirit::read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, Value& value )
{
begin = read_range_or_throw( begin, end, value );
}
#ifndef BOOST_NO_STD_WSTRING
bool json_spirit::read( const std::wstring& s, wValue& value )
{
return read_string( s, value );
}
void json_spirit::read_or_throw( const std::wstring& s, wValue& value )
{
read_string_or_throw( s, value );
}
bool json_spirit::read( std::wistream& is, wValue& value )
{
return read_stream( is, value );
}
void json_spirit::read_or_throw( std::wistream& is, wValue& value )
{
read_stream_or_throw( is, value );
}
bool json_spirit::read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value )
{
return read_range( begin, end, value );
}
void json_spirit::read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value )
{
begin = read_range_or_throw( begin, end, value );
}
#endif
bool json_spirit::read( const std::string& s, mValue& value )
{
return read_string( s, value );
}
void json_spirit::read_or_throw( const std::string& s, mValue& value )
{
read_string_or_throw( s, value );
}
bool json_spirit::read( std::istream& is, mValue& value )
{
return read_stream( is, value );
}
void json_spirit::read_or_throw( std::istream& is, mValue& value )
{
read_stream_or_throw( is, value );
}
bool json_spirit::read( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value )
{
return read_range( begin, end, value );
}
void json_spirit::read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value )
{
begin = read_range_or_throw( begin, end, value );
}
#ifndef BOOST_NO_STD_WSTRING
bool json_spirit::read( const std::wstring& s, wmValue& value )
{
return read_string( s, value );
}
void json_spirit::read_or_throw( const std::wstring& s, wmValue& value )
{
read_string_or_throw( s, value );
}
bool json_spirit::read( std::wistream& is, wmValue& value )
{
return read_stream( is, value );
}
void json_spirit::read_or_throw( std::wistream& is, wmValue& value )
{
read_stream_or_throw( is, value );
}
bool json_spirit::read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value )
{
return read_range( begin, end, value );
}
void json_spirit::read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value )
{
begin = read_range_or_throw( begin, end, value );
}
#endif

62
json/json_spirit_reader.h Normal file
View File

@@ -0,0 +1,62 @@
#ifndef JSON_SPIRIT_READER
#define JSON_SPIRIT_READER
// Copyright John W. Wilkinson 2007 - 2009.
// Distributed under the MIT License, see accompanying file LICENSE.txt
// json spirit version 4.03
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include "json_spirit_value.h"
#include "json_spirit_error_position.h"
#include <iostream>
namespace json_spirit
{
// functions to reads a JSON values
bool read( const std::string& s, Value& value );
bool read( std::istream& is, Value& value );
bool read( std::string::const_iterator& begin, std::string::const_iterator end, Value& value );
void read_or_throw( const std::string& s, Value& value );
void read_or_throw( std::istream& is, Value& value );
void read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, Value& value );
#ifndef BOOST_NO_STD_WSTRING
bool read( const std::wstring& s, wValue& value );
bool read( std::wistream& is, wValue& value );
bool read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value );
void read_or_throw( const std::wstring& s, wValue& value );
void read_or_throw( std::wistream& is, wValue& value );
void read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wValue& value );
#endif
bool read( const std::string& s, mValue& value );
bool read( std::istream& is, mValue& value );
bool read( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value );
void read_or_throw( const std::string& s, mValue& value );
void read_or_throw( std::istream& is, mValue& value );
void read_or_throw( std::string::const_iterator& begin, std::string::const_iterator end, mValue& value );
#ifndef BOOST_NO_STD_WSTRING
bool read( const std::wstring& s, wmValue& value );
bool read( std::wistream& is, wmValue& value );
bool read( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value );
void read_or_throw( const std::wstring& s, wmValue& value );
void read_or_throw( std::wistream& is, wmValue& value );
void read_or_throw( std::wstring::const_iterator& begin, std::wstring::const_iterator end, wmValue& value );
#endif
}
#endif

View File

@@ -0,0 +1,612 @@
#ifndef JSON_SPIRIT_READER_TEMPLATE
#define JSON_SPIRIT_READER_TEMPLATE
// Copyright John W. Wilkinson 2007 - 2009.
// Distributed under the MIT License, see accompanying file LICENSE.txt
// json spirit version 4.03
#include "json_spirit_value.h"
#include "json_spirit_error_position.h"
//#define BOOST_SPIRIT_THREADSAFE // uncomment for multithreaded use, requires linking to boost.thread
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/version.hpp>
#if BOOST_VERSION >= 103800
#include <boost/spirit/include/classic_core.hpp>
#include <boost/spirit/include/classic_confix.hpp>
#include <boost/spirit/include/classic_escape_char.hpp>
#include <boost/spirit/include/classic_multi_pass.hpp>
#include <boost/spirit/include/classic_position_iterator.hpp>
#define spirit_namespace boost::spirit::classic
#else
#include <boost/spirit/core.hpp>
#include <boost/spirit/utility/confix.hpp>
#include <boost/spirit/utility/escape_char.hpp>
#include <boost/spirit/iterator/multi_pass.hpp>
#include <boost/spirit/iterator/position_iterator.hpp>
#define spirit_namespace boost::spirit
#endif
namespace json_spirit
{
const spirit_namespace::int_parser < boost::int64_t > int64_p = spirit_namespace::int_parser < boost::int64_t >();
const spirit_namespace::uint_parser< boost::uint64_t > uint64_p = spirit_namespace::uint_parser< boost::uint64_t >();
template< class Iter_type >
bool is_eq( Iter_type first, Iter_type last, const char* c_str )
{
for( Iter_type i = first; i != last; ++i, ++c_str )
{
if( *c_str == 0 ) return false;
if( *i != *c_str ) return false;
}
return true;
}
template< class Char_type >
Char_type hex_to_num( const Char_type c )
{
if( ( c >= '0' ) && ( c <= '9' ) ) return c - '0';
if( ( c >= 'a' ) && ( c <= 'f' ) ) return c - 'a' + 10;
if( ( c >= 'A' ) && ( c <= 'F' ) ) return c - 'A' + 10;
return 0;
}
template< class Char_type, class Iter_type >
Char_type hex_str_to_char( Iter_type& begin )
{
const Char_type c1( *( ++begin ) );
const Char_type c2( *( ++begin ) );
return ( hex_to_num( c1 ) << 4 ) + hex_to_num( c2 );
}
template< class Char_type, class Iter_type >
Char_type unicode_str_to_char( Iter_type& begin )
{
const Char_type c1( *( ++begin ) );
const Char_type c2( *( ++begin ) );
const Char_type c3( *( ++begin ) );
const Char_type c4( *( ++begin ) );
return ( hex_to_num( c1 ) << 12 ) +
( hex_to_num( c2 ) << 8 ) +
( hex_to_num( c3 ) << 4 ) +
hex_to_num( c4 );
}
template< class String_type >
void append_esc_char_and_incr_iter( String_type& s,
typename String_type::const_iterator& begin,
typename String_type::const_iterator end )
{
typedef typename String_type::value_type Char_type;
const Char_type c2( *begin );
switch( c2 )
{
case 't': s += '\t'; break;
case 'b': s += '\b'; break;
case 'f': s += '\f'; break;
case 'n': s += '\n'; break;
case 'r': s += '\r'; break;
case '\\': s += '\\'; break;
case '/': s += '/'; break;
case '"': s += '"'; break;
case 'x':
{
if( end - begin >= 3 ) // expecting "xHH..."
{
s += hex_str_to_char< Char_type >( begin );
}
break;
}
case 'u':
{
if( end - begin >= 5 ) // expecting "uHHHH..."
{
s += unicode_str_to_char< Char_type >( begin );
}
break;
}
}
}
template< class String_type >
String_type substitute_esc_chars( typename String_type::const_iterator begin,
typename String_type::const_iterator end )
{
typedef typename String_type::const_iterator Iter_type;
if( end - begin < 2 ) return String_type( begin, end );
String_type result;
result.reserve( end - begin );
const Iter_type end_minus_1( end - 1 );
Iter_type substr_start = begin;
Iter_type i = begin;
for( ; i < end_minus_1; ++i )
{
if( *i == '\\' )
{
result.append( substr_start, i );
++i; // skip the '\'
append_esc_char_and_incr_iter( result, i, end );
substr_start = i + 1;
}
}
result.append( substr_start, end );
return result;
}
template< class String_type >
String_type get_str_( typename String_type::const_iterator begin,
typename String_type::const_iterator end )
{
assert( end - begin >= 2 );
typedef typename String_type::const_iterator Iter_type;
Iter_type str_without_quotes( ++begin );
Iter_type end_without_quotes( --end );
return substitute_esc_chars< String_type >( str_without_quotes, end_without_quotes );
}
inline std::string get_str( std::string::const_iterator begin, std::string::const_iterator end )
{
return get_str_< std::string >( begin, end );
}
inline std::wstring get_str( std::wstring::const_iterator begin, std::wstring::const_iterator end )
{
return get_str_< std::wstring >( begin, end );
}
template< class String_type, class Iter_type >
String_type get_str( Iter_type begin, Iter_type end )
{
const String_type tmp( begin, end ); // convert multipass iterators to string iterators
return get_str( tmp.begin(), tmp.end() );
}
// this class's methods get called by the spirit parse resulting
// in the creation of a JSON object or array
//
// NB Iter_type could be a std::string iterator, wstring iterator, a position iterator or a multipass iterator
//
template< class Value_type, class Iter_type >
class Semantic_actions
{
public:
typedef typename Value_type::Config_type Config_type;
typedef typename Config_type::String_type String_type;
typedef typename Config_type::Object_type Object_type;
typedef typename Config_type::Array_type Array_type;
typedef typename String_type::value_type Char_type;
Semantic_actions( Value_type& value )
: value_( value )
, current_p_( 0 )
{
}
void begin_obj( Char_type c )
{
assert( c == '{' );
begin_compound< Object_type >();
}
void end_obj( Char_type c )
{
assert( c == '}' );
end_compound();
}
void begin_array( Char_type c )
{
assert( c == '[' );
begin_compound< Array_type >();
}
void end_array( Char_type c )
{
assert( c == ']' );
end_compound();
}
void new_name( Iter_type begin, Iter_type end )
{
assert( current_p_->type() == obj_type );
name_ = get_str< String_type >( begin, end );
}
void new_str( Iter_type begin, Iter_type end )
{
add_to_current( get_str< String_type >( begin, end ) );
}
void new_true( Iter_type begin, Iter_type end )
{
assert( is_eq( begin, end, "true" ) );
add_to_current( true );
}
void new_false( Iter_type begin, Iter_type end )
{
assert( is_eq( begin, end, "false" ) );
add_to_current( false );
}
void new_null( Iter_type begin, Iter_type end )
{
assert( is_eq( begin, end, "null" ) );
add_to_current( Value_type() );
}
void new_int( boost::int64_t i )
{
add_to_current( i );
}
void new_uint64( boost::uint64_t ui )
{
add_to_current( ui );
}
void new_real( double d )
{
add_to_current( d );
}
private:
Semantic_actions& operator=( const Semantic_actions& );
// to prevent "assignment operator could not be generated" warning
Value_type* add_first( const Value_type& value )
{
assert( current_p_ == 0 );
value_ = value;
current_p_ = &value_;
return current_p_;
}
template< class Array_or_obj >
void begin_compound()
{
if( current_p_ == 0 )
{
add_first( Array_or_obj() );
}
else
{
stack_.push_back( current_p_ );
Array_or_obj new_array_or_obj; // avoid copy by building new array or object in place
current_p_ = add_to_current( new_array_or_obj );
}
}
void end_compound()
{
if( current_p_ != &value_ )
{
current_p_ = stack_.back();
stack_.pop_back();
}
}
Value_type* add_to_current( const Value_type& value )
{
if( current_p_ == 0 )
{
return add_first( value );
}
else if( current_p_->type() == array_type )
{
current_p_->get_array().push_back( value );
return &current_p_->get_array().back();
}
assert( current_p_->type() == obj_type );
return &Config_type::add( current_p_->get_obj(), name_, value );
}
Value_type& value_; // this is the object or array that is being created
Value_type* current_p_; // the child object or array that is currently being constructed
std::vector< Value_type* > stack_; // previous child objects and arrays
String_type name_; // of current name/value pair
};
template< typename Iter_type >
void throw_error( spirit_namespace::position_iterator< Iter_type > i, const std::string& reason )
{
throw Error_position( i.get_position().line, i.get_position().column, reason );
}
template< typename Iter_type >
void throw_error( Iter_type i, const std::string& reason )
{
throw reason;
}
// the spirit grammer
//
template< class Value_type, class Iter_type >
class Json_grammer : public spirit_namespace::grammar< Json_grammer< Value_type, Iter_type > >
{
public:
typedef Semantic_actions< Value_type, Iter_type > Semantic_actions_t;
Json_grammer( Semantic_actions_t& semantic_actions )
: actions_( semantic_actions )
{
}
static void throw_not_value( Iter_type begin, Iter_type end )
{
throw_error( begin, "not a value" );
}
static void throw_not_array( Iter_type begin, Iter_type end )
{
throw_error( begin, "not an array" );
}
static void throw_not_object( Iter_type begin, Iter_type end )
{
throw_error( begin, "not an object" );
}
static void throw_not_pair( Iter_type begin, Iter_type end )
{
throw_error( begin, "not a pair" );
}
static void throw_not_colon( Iter_type begin, Iter_type end )
{
throw_error( begin, "no colon in pair" );
}
static void throw_not_string( Iter_type begin, Iter_type end )
{
throw_error( begin, "not a string" );
}
template< typename ScannerT >
class definition
{
public:
definition( const Json_grammer& self )
{
using namespace spirit_namespace;
typedef typename Value_type::String_type::value_type Char_type;
// first we convert the semantic action class methods to functors with the
// parameter signature expected by spirit
typedef boost::function< void( Char_type ) > Char_action;
typedef boost::function< void( Iter_type, Iter_type ) > Str_action;
typedef boost::function< void( double ) > Real_action;
typedef boost::function< void( boost::int64_t ) > Int_action;
typedef boost::function< void( boost::uint64_t ) > Uint64_action;
Char_action begin_obj ( boost::bind( &Semantic_actions_t::begin_obj, &self.actions_, _1 ) );
Char_action end_obj ( boost::bind( &Semantic_actions_t::end_obj, &self.actions_, _1 ) );
Char_action begin_array( boost::bind( &Semantic_actions_t::begin_array, &self.actions_, _1 ) );
Char_action end_array ( boost::bind( &Semantic_actions_t::end_array, &self.actions_, _1 ) );
Str_action new_name ( boost::bind( &Semantic_actions_t::new_name, &self.actions_, _1, _2 ) );
Str_action new_str ( boost::bind( &Semantic_actions_t::new_str, &self.actions_, _1, _2 ) );
Str_action new_true ( boost::bind( &Semantic_actions_t::new_true, &self.actions_, _1, _2 ) );
Str_action new_false ( boost::bind( &Semantic_actions_t::new_false, &self.actions_, _1, _2 ) );
Str_action new_null ( boost::bind( &Semantic_actions_t::new_null, &self.actions_, _1, _2 ) );
Real_action new_real ( boost::bind( &Semantic_actions_t::new_real, &self.actions_, _1 ) );
Int_action new_int ( boost::bind( &Semantic_actions_t::new_int, &self.actions_, _1 ) );
Uint64_action new_uint64 ( boost::bind( &Semantic_actions_t::new_uint64, &self.actions_, _1 ) );
// actual grammer
json_
= value_ | eps_p[ &throw_not_value ]
;
value_
= string_[ new_str ]
| number_
| object_
| array_
| str_p( "true" ) [ new_true ]
| str_p( "false" )[ new_false ]
| str_p( "null" ) [ new_null ]
;
object_
= ch_p('{')[ begin_obj ]
>> !members_
>> ( ch_p('}')[ end_obj ] | eps_p[ &throw_not_object ] )
;
members_
= pair_ >> *( ',' >> pair_ )
;
pair_
= string_[ new_name ]
>> ( ':' | eps_p[ &throw_not_colon ] )
>> ( value_ | eps_p[ &throw_not_value ] )
;
array_
= ch_p('[')[ begin_array ]
>> !elements_
>> ( ch_p(']')[ end_array ] | eps_p[ &throw_not_array ] )
;
elements_
= value_ >> *( ',' >> value_ )
;
string_
= lexeme_d // this causes white space inside a string to be retained
[
confix_p
(
'"',
*lex_escape_ch_p,
'"'
)
]
;
number_
= strict_real_p[ new_real ]
| int64_p [ new_int ]
| uint64_p [ new_uint64 ]
;
}
spirit_namespace::rule< ScannerT > json_, object_, members_, pair_, array_, elements_, value_, string_, number_;
const spirit_namespace::rule< ScannerT >& start() const { return json_; }
};
private:
Json_grammer& operator=( const Json_grammer& ); // to prevent "assignment operator could not be generated" warning
Semantic_actions_t& actions_;
};
template< class Iter_type, class Value_type >
Iter_type read_range_or_throw( Iter_type begin, Iter_type end, Value_type& value )
{
Semantic_actions< Value_type, Iter_type > semantic_actions( value );
const spirit_namespace::parse_info< Iter_type > info =
spirit_namespace::parse( begin, end,
Json_grammer< Value_type, Iter_type >( semantic_actions ),
spirit_namespace::space_p );
if( !info.hit )
{
assert( false ); // in theory exception should already have been thrown
throw_error( info.stop, "error" );
}
return info.stop;
}
template< class Iter_type, class Value_type >
void add_posn_iter_and_read_range_or_throw( Iter_type begin, Iter_type end, Value_type& value )
{
typedef spirit_namespace::position_iterator< Iter_type > Posn_iter_t;
const Posn_iter_t posn_begin( begin, end );
const Posn_iter_t posn_end( end, end );
read_range_or_throw( posn_begin, posn_end, value );
}
template< class Iter_type, class Value_type >
bool read_range( Iter_type& begin, Iter_type end, Value_type& value )
{
try
{
begin = read_range_or_throw( begin, end, value );
return true;
}
catch( ... )
{
return false;
}
}
template< class String_type, class Value_type >
void read_string_or_throw( const String_type& s, Value_type& value )
{
add_posn_iter_and_read_range_or_throw( s.begin(), s.end(), value );
}
template< class String_type, class Value_type >
bool read_string( const String_type& s, Value_type& value )
{
typename String_type::const_iterator begin = s.begin();
return read_range( begin, s.end(), value );
}
template< class Istream_type >
struct Multi_pass_iters
{
typedef typename Istream_type::char_type Char_type;
typedef std::istream_iterator< Char_type, Char_type > istream_iter;
typedef spirit_namespace::multi_pass< istream_iter > Mp_iter;
Multi_pass_iters( Istream_type& is )
{
is.unsetf( std::ios::skipws );
begin_ = spirit_namespace::make_multi_pass( istream_iter( is ) );
end_ = spirit_namespace::make_multi_pass( istream_iter() );
}
Mp_iter begin_;
Mp_iter end_;
};
template< class Istream_type, class Value_type >
bool read_stream( Istream_type& is, Value_type& value )
{
Multi_pass_iters< Istream_type > mp_iters( is );
return read_range( mp_iters.begin_, mp_iters.end_, value );
}
template< class Istream_type, class Value_type >
void read_stream_or_throw( Istream_type& is, Value_type& value )
{
const Multi_pass_iters< Istream_type > mp_iters( is );
add_posn_iter_and_read_range_or_throw( mp_iters.begin_, mp_iters.end_, value );
}
}
#endif

View File

@@ -0,0 +1,70 @@
#ifndef JSON_SPIRIT_READ_STREAM
#define JSON_SPIRIT_READ_STREAM
// Copyright John W. Wilkinson 2007 - 2009.
// Distributed under the MIT License, see accompanying file LICENSE.txt
// json spirit version 4.03
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include "json_spirit_reader_template.h"
namespace json_spirit
{
// these classes allows you to read multiple top level contiguous values from a stream,
// the normal stream read functions have a bug that prevent multiple top level values
// from being read unless they are separated by spaces
template< class Istream_type, class Value_type >
class Stream_reader
{
public:
Stream_reader( Istream_type& is )
: iters_( is )
{
}
bool read_next( Value_type& value )
{
return read_range( iters_.begin_, iters_.end_, value );
}
private:
typedef Multi_pass_iters< Istream_type > Mp_iters;
Mp_iters iters_;
};
template< class Istream_type, class Value_type >
class Stream_reader_thrower
{
public:
Stream_reader_thrower( Istream_type& is )
: iters_( is )
, posn_begin_( iters_.begin_, iters_.end_ )
, posn_end_( iters_.end_, iters_.end_ )
{
}
void read_next( Value_type& value )
{
posn_begin_ = read_range_or_throw( posn_begin_, posn_end_, value );
}
private:
typedef Multi_pass_iters< Istream_type > Mp_iters;
typedef spirit_namespace::position_iterator< typename Mp_iters::Mp_iter > Posn_iter_t;
Mp_iters iters_;
Posn_iter_t posn_begin_, posn_end_;
};
}
#endif

61
json/json_spirit_utils.h Normal file
View File

@@ -0,0 +1,61 @@
#ifndef JSON_SPIRIT_UTILS
#define JSON_SPIRIT_UTILS
// Copyright John W. Wilkinson 2007 - 2009.
// Distributed under the MIT License, see accompanying file LICENSE.txt
// json spirit version 4.03
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include "json_spirit_value.h"
#include <map>
namespace json_spirit
{
template< class Obj_t, class Map_t >
void obj_to_map( const Obj_t& obj, Map_t& mp_obj )
{
mp_obj.clear();
for( typename Obj_t::const_iterator i = obj.begin(); i != obj.end(); ++i )
{
mp_obj[ i->name_ ] = i->value_;
}
}
template< class Obj_t, class Map_t >
void map_to_obj( const Map_t& mp_obj, Obj_t& obj )
{
obj.clear();
for( typename Map_t::const_iterator i = mp_obj.begin(); i != mp_obj.end(); ++i )
{
obj.push_back( typename Obj_t::value_type( i->first, i->second ) );
}
}
typedef std::map< std::string, Value > Mapped_obj;
#ifndef BOOST_NO_STD_WSTRING
typedef std::map< std::wstring, wValue > wMapped_obj;
#endif
template< class Object_type, class String_type >
const typename Object_type::value_type::Value_type& find_value( const Object_type& obj, const String_type& name )
{
for( typename Object_type::const_iterator i = obj.begin(); i != obj.end(); ++i )
{
if( i->name_ == name )
{
return i->value_;
}
}
return Object_type::value_type::Value_type::null;
}
}
#endif

View File

@@ -0,0 +1,8 @@
/* Copyright (c) 2007 John W Wilkinson
This source code can be used for any purpose as long as
this comment is retained. */
// json spirit version 2.00
#include "json_spirit_value.h"

534
json/json_spirit_value.h Normal file
View File

@@ -0,0 +1,534 @@
#ifndef JSON_SPIRIT_VALUE
#define JSON_SPIRIT_VALUE
// Copyright John W. Wilkinson 2007 - 2009.
// Distributed under the MIT License, see accompanying file LICENSE.txt
// json spirit version 4.03
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <vector>
#include <map>
#include <string>
#include <cassert>
#include <sstream>
#include <stdexcept>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/variant.hpp>
namespace json_spirit
{
enum Value_type{ obj_type, array_type, str_type, bool_type, int_type, real_type, null_type };
static const char* Value_type_name[]={"obj", "array", "str", "bool", "int", "real", "null"};
template< class Config > // Config determines whether the value uses std::string or std::wstring and
// whether JSON Objects are represented as vectors or maps
class Value_impl
{
public:
typedef Config Config_type;
typedef typename Config::String_type String_type;
typedef typename Config::Object_type Object;
typedef typename Config::Array_type Array;
typedef typename String_type::const_pointer Const_str_ptr; // eg const char*
Value_impl(); // creates null value
Value_impl( Const_str_ptr value );
Value_impl( const String_type& value );
Value_impl( const Object& value );
Value_impl( const Array& value );
Value_impl( bool value );
Value_impl( int value );
Value_impl( boost::int64_t value );
Value_impl( boost::uint64_t value );
Value_impl( double value );
Value_impl( const Value_impl& other );
bool operator==( const Value_impl& lhs ) const;
Value_impl& operator=( const Value_impl& lhs );
Value_type type() const;
bool is_uint64() const;
bool is_null() const;
const String_type& get_str() const;
const Object& get_obj() const;
const Array& get_array() const;
bool get_bool() const;
int get_int() const;
boost::int64_t get_int64() const;
boost::uint64_t get_uint64() const;
double get_real() const;
Object& get_obj();
Array& get_array();
template< typename T > T get_value() const; // example usage: int i = value.get_value< int >();
// or double d = value.get_value< double >();
static const Value_impl null;
private:
void check_type( const Value_type vtype ) const;
typedef boost::variant< String_type,
boost::recursive_wrapper< Object >, boost::recursive_wrapper< Array >,
bool, boost::int64_t, double > Variant;
Value_type type_;
Variant v_;
bool is_uint64_;
};
// vector objects
template< class Config >
struct Pair_impl
{
typedef typename Config::String_type String_type;
typedef typename Config::Value_type Value_type;
Pair_impl( const String_type& name, const Value_type& value );
bool operator==( const Pair_impl& lhs ) const;
String_type name_;
Value_type value_;
};
template< class String >
struct Config_vector
{
typedef String String_type;
typedef Value_impl< Config_vector > Value_type;
typedef Pair_impl < Config_vector > Pair_type;
typedef std::vector< Value_type > Array_type;
typedef std::vector< Pair_type > Object_type;
static Value_type& add( Object_type& obj, const String_type& name, const Value_type& value )
{
obj.push_back( Pair_type( name , value ) );
return obj.back().value_;
}
static String_type get_name( const Pair_type& pair )
{
return pair.name_;
}
static Value_type get_value( const Pair_type& pair )
{
return pair.value_;
}
};
// typedefs for ASCII
typedef Config_vector< std::string > Config;
typedef Config::Value_type Value;
typedef Config::Pair_type Pair;
typedef Config::Object_type Object;
typedef Config::Array_type Array;
// typedefs for Unicode
#ifndef BOOST_NO_STD_WSTRING
typedef Config_vector< std::wstring > wConfig;
typedef wConfig::Value_type wValue;
typedef wConfig::Pair_type wPair;
typedef wConfig::Object_type wObject;
typedef wConfig::Array_type wArray;
#endif
// map objects
template< class String >
struct Config_map
{
typedef String String_type;
typedef Value_impl< Config_map > Value_type;
typedef std::vector< Value_type > Array_type;
typedef std::map< String_type, Value_type > Object_type;
typedef typename Object_type::value_type Pair_type;
static Value_type& add( Object_type& obj, const String_type& name, const Value_type& value )
{
return obj[ name ] = value;
}
static String_type get_name( const Pair_type& pair )
{
return pair.first;
}
static Value_type get_value( const Pair_type& pair )
{
return pair.second;
}
};
// typedefs for ASCII
typedef Config_map< std::string > mConfig;
typedef mConfig::Value_type mValue;
typedef mConfig::Object_type mObject;
typedef mConfig::Array_type mArray;
// typedefs for Unicode
#ifndef BOOST_NO_STD_WSTRING
typedef Config_map< std::wstring > wmConfig;
typedef wmConfig::Value_type wmValue;
typedef wmConfig::Object_type wmObject;
typedef wmConfig::Array_type wmArray;
#endif
///////////////////////////////////////////////////////////////////////////////////////////////
//
// implementation
template< class Config >
const Value_impl< Config > Value_impl< Config >::null;
template< class Config >
Value_impl< Config >::Value_impl()
: type_( null_type )
, is_uint64_( false )
{
}
template< class Config >
Value_impl< Config >::Value_impl( const Const_str_ptr value )
: type_( str_type )
, v_( String_type( value ) )
, is_uint64_( false )
{
}
template< class Config >
Value_impl< Config >::Value_impl( const String_type& value )
: type_( str_type )
, v_( value )
, is_uint64_( false )
{
}
template< class Config >
Value_impl< Config >::Value_impl( const Object& value )
: type_( obj_type )
, v_( value )
, is_uint64_( false )
{
}
template< class Config >
Value_impl< Config >::Value_impl( const Array& value )
: type_( array_type )
, v_( value )
, is_uint64_( false )
{
}
template< class Config >
Value_impl< Config >::Value_impl( bool value )
: type_( bool_type )
, v_( value )
, is_uint64_( false )
{
}
template< class Config >
Value_impl< Config >::Value_impl( int value )
: type_( int_type )
, v_( static_cast< boost::int64_t >( value ) )
, is_uint64_( false )
{
}
template< class Config >
Value_impl< Config >::Value_impl( boost::int64_t value )
: type_( int_type )
, v_( value )
, is_uint64_( false )
{
}
template< class Config >
Value_impl< Config >::Value_impl( boost::uint64_t value )
: type_( int_type )
, v_( static_cast< boost::int64_t >( value ) )
, is_uint64_( true )
{
}
template< class Config >
Value_impl< Config >::Value_impl( double value )
: type_( real_type )
, v_( value )
, is_uint64_( false )
{
}
template< class Config >
Value_impl< Config >::Value_impl( const Value_impl< Config >& other )
: type_( other.type() )
, v_( other.v_ )
, is_uint64_( other.is_uint64_ )
{
}
template< class Config >
Value_impl< Config >& Value_impl< Config >::operator=( const Value_impl& lhs )
{
Value_impl tmp( lhs );
std::swap( type_, tmp.type_ );
std::swap( v_, tmp.v_ );
std::swap( is_uint64_, tmp.is_uint64_ );
return *this;
}
template< class Config >
bool Value_impl< Config >::operator==( const Value_impl& lhs ) const
{
if( this == &lhs ) return true;
if( type() != lhs.type() ) return false;
return v_ == lhs.v_;
}
template< class Config >
Value_type Value_impl< Config >::type() const
{
return type_;
}
template< class Config >
bool Value_impl< Config >::is_uint64() const
{
return is_uint64_;
}
template< class Config >
bool Value_impl< Config >::is_null() const
{
return type() == null_type;
}
template< class Config >
void Value_impl< Config >::check_type( const Value_type vtype ) const
{
if( type() != vtype )
{
std::ostringstream os;
/// satoshi: tell the types by name instead of by number
os << "value is type " << Value_type_name[type()] << ", expected " << Value_type_name[vtype];
throw std::runtime_error( os.str() );
}
}
template< class Config >
const typename Config::String_type& Value_impl< Config >::get_str() const
{
check_type( str_type );
return *boost::get< String_type >( &v_ );
}
template< class Config >
const typename Value_impl< Config >::Object& Value_impl< Config >::get_obj() const
{
check_type( obj_type );
return *boost::get< Object >( &v_ );
}
template< class Config >
const typename Value_impl< Config >::Array& Value_impl< Config >::get_array() const
{
check_type( array_type );
return *boost::get< Array >( &v_ );
}
template< class Config >
bool Value_impl< Config >::get_bool() const
{
check_type( bool_type );
return boost::get< bool >( v_ );
}
template< class Config >
int Value_impl< Config >::get_int() const
{
check_type( int_type );
return static_cast< int >( get_int64() );
}
template< class Config >
boost::int64_t Value_impl< Config >::get_int64() const
{
check_type( int_type );
return boost::get< boost::int64_t >( v_ );
}
template< class Config >
boost::uint64_t Value_impl< Config >::get_uint64() const
{
check_type( int_type );
return static_cast< boost::uint64_t >( get_int64() );
}
template< class Config >
double Value_impl< Config >::get_real() const
{
if( type() == int_type )
{
return is_uint64() ? static_cast< double >( get_uint64() )
: static_cast< double >( get_int64() );
}
check_type( real_type );
return boost::get< double >( v_ );
}
template< class Config >
typename Value_impl< Config >::Object& Value_impl< Config >::get_obj()
{
check_type( obj_type );
return *boost::get< Object >( &v_ );
}
template< class Config >
typename Value_impl< Config >::Array& Value_impl< Config >::get_array()
{
check_type( array_type );
return *boost::get< Array >( &v_ );
}
template< class Config >
Pair_impl< Config >::Pair_impl( const String_type& name, const Value_type& value )
: name_( name )
, value_( value )
{
}
template< class Config >
bool Pair_impl< Config >::operator==( const Pair_impl< Config >& lhs ) const
{
if( this == &lhs ) return true;
return ( name_ == lhs.name_ ) && ( value_ == lhs.value_ );
}
// converts a C string, ie. 8 bit char array, to a string object
//
template < class String_type >
String_type to_str( const char* c_str )
{
String_type result;
for( const char* p = c_str; *p != 0; ++p )
{
result += *p;
}
return result;
}
//
namespace internal_
{
template< typename T >
struct Type_to_type
{
};
template< class Value >
int get_value( const Value& value, Type_to_type< int > )
{
return value.get_int();
}
template< class Value >
boost::int64_t get_value( const Value& value, Type_to_type< boost::int64_t > )
{
return value.get_int64();
}
template< class Value >
boost::uint64_t get_value( const Value& value, Type_to_type< boost::uint64_t > )
{
return value.get_uint64();
}
template< class Value >
double get_value( const Value& value, Type_to_type< double > )
{
return value.get_real();
}
template< class Value >
typename Value::String_type get_value( const Value& value, Type_to_type< typename Value::String_type > )
{
return value.get_str();
}
template< class Value >
typename Value::Array get_value( const Value& value, Type_to_type< typename Value::Array > )
{
return value.get_array();
}
template< class Value >
typename Value::Object get_value( const Value& value, Type_to_type< typename Value::Object > )
{
return value.get_obj();
}
template< class Value >
bool get_value( const Value& value, Type_to_type< bool > )
{
return value.get_bool();
}
}
template< class Config >
template< typename T >
T Value_impl< Config >::get_value() const
{
return internal_::get_value( *this, internal_::Type_to_type< T >() );
}
}
#endif

View File

@@ -0,0 +1,95 @@
// Copyright John W. Wilkinson 2007 - 2009.
// Distributed under the MIT License, see accompanying file LICENSE.txt
// json spirit version 4.03
#include "json_spirit_writer.h"
#include "json_spirit_writer_template.h"
void json_spirit::write( const Value& value, std::ostream& os )
{
write_stream( value, os, false );
}
void json_spirit::write_formatted( const Value& value, std::ostream& os )
{
write_stream( value, os, true );
}
std::string json_spirit::write( const Value& value )
{
return write_string( value, false );
}
std::string json_spirit::write_formatted( const Value& value )
{
return write_string( value, true );
}
#ifndef BOOST_NO_STD_WSTRING
void json_spirit::write( const wValue& value, std::wostream& os )
{
write_stream( value, os, false );
}
void json_spirit::write_formatted( const wValue& value, std::wostream& os )
{
write_stream( value, os, true );
}
std::wstring json_spirit::write( const wValue& value )
{
return write_string( value, false );
}
std::wstring json_spirit::write_formatted( const wValue& value )
{
return write_string( value, true );
}
#endif
void json_spirit::write( const mValue& value, std::ostream& os )
{
write_stream( value, os, false );
}
void json_spirit::write_formatted( const mValue& value, std::ostream& os )
{
write_stream( value, os, true );
}
std::string json_spirit::write( const mValue& value )
{
return write_string( value, false );
}
std::string json_spirit::write_formatted( const mValue& value )
{
return write_string( value, true );
}
#ifndef BOOST_NO_STD_WSTRING
void json_spirit::write( const wmValue& value, std::wostream& os )
{
write_stream( value, os, false );
}
void json_spirit::write_formatted( const wmValue& value, std::wostream& os )
{
write_stream( value, os, true );
}
std::wstring json_spirit::write( const wmValue& value )
{
return write_string( value, false );
}
std::wstring json_spirit::write_formatted( const wmValue& value )
{
return write_string( value, true );
}
#endif

50
json/json_spirit_writer.h Normal file
View File

@@ -0,0 +1,50 @@
#ifndef JSON_SPIRIT_WRITER
#define JSON_SPIRIT_WRITER
// Copyright John W. Wilkinson 2007 - 2009.
// Distributed under the MIT License, see accompanying file LICENSE.txt
// json spirit version 4.03
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include "json_spirit_value.h"
#include <iostream>
namespace json_spirit
{
// functions to convert JSON Values to text,
// the "formatted" versions add whitespace to format the output nicely
void write ( const Value& value, std::ostream& os );
void write_formatted( const Value& value, std::ostream& os );
std::string write ( const Value& value );
std::string write_formatted( const Value& value );
#ifndef BOOST_NO_STD_WSTRING
void write ( const wValue& value, std::wostream& os );
void write_formatted( const wValue& value, std::wostream& os );
std::wstring write ( const wValue& value );
std::wstring write_formatted( const wValue& value );
#endif
void write ( const mValue& value, std::ostream& os );
void write_formatted( const mValue& value, std::ostream& os );
std::string write ( const mValue& value );
std::string write_formatted( const mValue& value );
#ifndef BOOST_NO_STD_WSTRING
void write ( const wmValue& value, std::wostream& os );
void write_formatted( const wmValue& value, std::wostream& os );
std::wstring write ( const wmValue& value );
std::wstring write_formatted( const wmValue& value );
#endif
}
#endif

View File

@@ -0,0 +1,245 @@
#ifndef JSON_SPIRIT_WRITER_TEMPLATE
#define JSON_SPIRIT_WRITER_TEMPLATE
// Copyright John W. Wilkinson 2007 - 2009.
// Distributed under the MIT License, see accompanying file LICENSE.txt
// json spirit version 4.03
#include "json_spirit_value.h"
#include <cassert>
#include <sstream>
#include <iomanip>
namespace json_spirit
{
inline char to_hex_char( unsigned int c )
{
assert( c <= 0xF );
const char ch = static_cast< char >( c );
if( ch < 10 ) return '0' + ch;
return 'A' - 10 + ch;
}
template< class String_type >
String_type non_printable_to_string( unsigned int c )
{
typedef typename String_type::value_type Char_type;
String_type result( 6, '\\' );
result[1] = 'u';
result[ 5 ] = to_hex_char( c & 0x000F ); c >>= 4;
result[ 4 ] = to_hex_char( c & 0x000F ); c >>= 4;
result[ 3 ] = to_hex_char( c & 0x000F ); c >>= 4;
result[ 2 ] = to_hex_char( c & 0x000F );
return result;
}
template< typename Char_type, class String_type >
bool add_esc_char( Char_type c, String_type& s )
{
switch( c )
{
case '"': s += to_str< String_type >( "\\\"" ); return true;
case '\\': s += to_str< String_type >( "\\\\" ); return true;
case '\b': s += to_str< String_type >( "\\b" ); return true;
case '\f': s += to_str< String_type >( "\\f" ); return true;
case '\n': s += to_str< String_type >( "\\n" ); return true;
case '\r': s += to_str< String_type >( "\\r" ); return true;
case '\t': s += to_str< String_type >( "\\t" ); return true;
}
return false;
}
template< class String_type >
String_type add_esc_chars( const String_type& s )
{
typedef typename String_type::const_iterator Iter_type;
typedef typename String_type::value_type Char_type;
String_type result;
const Iter_type end( s.end() );
for( Iter_type i = s.begin(); i != end; ++i )
{
const Char_type c( *i );
if( add_esc_char( c, result ) ) continue;
const wint_t unsigned_c( ( c >= 0 ) ? c : 256 + c );
if( iswprint( unsigned_c ) )
{
result += c;
}
else
{
result += non_printable_to_string< String_type >( unsigned_c );
}
}
return result;
}
// this class generates the JSON text,
// it keeps track of the indentation level etc.
//
template< class Value_type, class Ostream_type >
class Generator
{
typedef typename Value_type::Config_type Config_type;
typedef typename Config_type::String_type String_type;
typedef typename Config_type::Object_type Object_type;
typedef typename Config_type::Array_type Array_type;
typedef typename String_type::value_type Char_type;
typedef typename Object_type::value_type Obj_member_type;
public:
Generator( const Value_type& value, Ostream_type& os, bool pretty )
: os_( os )
, indentation_level_( 0 )
, pretty_( pretty )
{
output( value );
}
private:
void output( const Value_type& value )
{
switch( value.type() )
{
case obj_type: output( value.get_obj() ); break;
case array_type: output( value.get_array() ); break;
case str_type: output( value.get_str() ); break;
case bool_type: output( value.get_bool() ); break;
case int_type: output_int( value ); break;
case real_type: os_ << std::showpoint << std::setprecision( 16 )
<< value.get_real(); break;
case null_type: os_ << "null"; break;
default: assert( false );
}
}
void output( const Object_type& obj )
{
output_array_or_obj( obj, '{', '}' );
}
void output( const Array_type& arr )
{
output_array_or_obj( arr, '[', ']' );
}
void output( const Obj_member_type& member )
{
output( Config_type::get_name( member ) ); space();
os_ << ':'; space();
output( Config_type::get_value( member ) );
}
void output_int( const Value_type& value )
{
if( value.is_uint64() )
{
os_ << value.get_uint64();
}
else
{
os_ << value.get_int64();
}
}
void output( const String_type& s )
{
os_ << '"' << add_esc_chars( s ) << '"';
}
void output( bool b )
{
os_ << to_str< String_type >( b ? "true" : "false" );
}
template< class T >
void output_array_or_obj( const T& t, Char_type start_char, Char_type end_char )
{
os_ << start_char; new_line();
++indentation_level_;
for( typename T::const_iterator i = t.begin(); i != t.end(); ++i )
{
indent(); output( *i );
typename T::const_iterator next = i;
if( ++next != t.end())
{
os_ << ',';
}
new_line();
}
--indentation_level_;
indent(); os_ << end_char;
}
void indent()
{
if( !pretty_ ) return;
for( int i = 0; i < indentation_level_; ++i )
{
os_ << " ";
}
}
void space()
{
if( pretty_ ) os_ << ' ';
}
void new_line()
{
if( pretty_ ) os_ << '\n';
}
Generator& operator=( const Generator& ); // to prevent "assignment operator could not be generated" warning
Ostream_type& os_;
int indentation_level_;
bool pretty_;
};
template< class Value_type, class Ostream_type >
void write_stream( const Value_type& value, Ostream_type& os, bool pretty )
{
Generator< Value_type, Ostream_type >( value, os, pretty );
}
template< class Value_type >
typename Value_type::String_type write_string( const Value_type& value, bool pretty )
{
typedef typename Value_type::String_type::value_type Char_type;
std::basic_ostringstream< Char_type > os;
write_stream( value, os, pretty );
return os.str();
}
}
#endif

View File

@@ -1,4 +1,4 @@
Copyright (c) 2009 Satoshi Nakamoto
Copyright (c) 2009-2010 Satoshi Nakamoto
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

5
locale/readme.txt Normal file
View File

@@ -0,0 +1,5 @@
put bitcoin.po and bitcoin.mo files at:
locale/<langcode>/LC_MESSAGES/bitcoin.mo and .po
.po is the sourcefile
.mo is the compiled translation

376
main.cpp
View File

@@ -1,4 +1,4 @@
// Copyright (c) 2009 Satoshi Nakamoto
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
@@ -26,6 +26,7 @@ CBlockIndex* pindexGenesisBlock = NULL;
int nBestHeight = -1;
uint256 hashBestChain = 0;
CBlockIndex* pindexBest = NULL;
int64 nTimeBestReceived = 0;
map<uint256, CBlock*> mapOrphanBlocks;
multimap<uint256, CBlock*> mapOrphanBlocksByPrev;
@@ -45,6 +46,9 @@ CKey keyUser;
map<uint256, int> mapRequestCount;
CCriticalSection cs_mapRequestCount;
map<string, string> mapAddressBook;
CCriticalSection cs_mapAddressBook;
// Settings
int fGenerateBitcoins = false;
int64 nTransactionFee = 0;
@@ -168,6 +172,27 @@ bool EraseFromWallet(uint256 hash)
return true;
}
void WalletUpdateSpent(const COutPoint& prevout)
{
// Anytime a signature is successfully verified, it's proof the outpoint is spent.
// Update the wallet spent flag if it doesn't know due to wallet.dat being
// restored from backup or the user making copies of wallet.dat.
CRITICAL_BLOCK(cs_mapWallet)
{
map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
if (mi != mapWallet.end())
{
CWalletTx& wtx = (*mi).second;
if (!wtx.fSpent && wtx.vout[prevout.n].IsMine())
{
printf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
wtx.fSpent = true;
wtx.WriteToDisk();
vWalletUpdated.push_back(prevout.hash);
}
}
}
}
@@ -552,7 +577,7 @@ bool CTransaction::RemoveFromMemoryPool()
int CMerkleTx::GetDepthInMainChain() const
int CMerkleTx::GetDepthInMainChain(int& nHeightRet) const
{
if (hashBlock == 0 || nIndex == -1)
return 0;
@@ -573,6 +598,7 @@ int CMerkleTx::GetDepthInMainChain() const
fMerkleVerified = true;
}
nHeightRet = pindex->nHeight;
return pindexBest->nHeight - pindex->nHeight + 1;
}
@@ -622,15 +648,44 @@ bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs)
void ReacceptWalletTransactions()
{
// Reaccept any txes of ours that aren't already in a block
CTxDB txdb("r");
CRITICAL_BLOCK(cs_mapWallet)
{
foreach(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
{
CWalletTx& wtx = item.second;
if (!wtx.IsCoinBase() && !txdb.ContainsTx(wtx.GetHash()))
wtx.AcceptWalletTransaction(txdb, false);
if (wtx.fSpent && wtx.IsCoinBase())
continue;
CTxIndex txindex;
if (txdb.ReadTxIndex(wtx.GetHash(), txindex))
{
// Update fSpent if a tx got spent somewhere else by a copy of wallet.dat
if (!wtx.fSpent)
{
if (txindex.vSpent.size() != wtx.vout.size())
{
printf("ERROR: ReacceptWalletTransactions() : txindex.vSpent.size() %d != wtx.vout.size() %d\n", txindex.vSpent.size(), wtx.vout.size());
continue;
}
for (int i = 0; i < txindex.vSpent.size(); i++)
{
if (!txindex.vSpent[i].IsNull() && wtx.vout[i].IsMine())
{
printf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
wtx.fSpent = true;
wtx.WriteToDisk();
break;
}
}
}
}
else
{
// Reaccept any txes of ours that aren't already in a block
if (!wtx.IsCoinBase())
wtx.AcceptWalletTransaction(txdb, false);
}
}
}
}
@@ -658,15 +713,20 @@ void CWalletTx::RelayWalletTransaction(CTxDB& txdb)
}
}
void RelayWalletTransactions()
void ResendWalletTransactions()
{
static int64 nLastTime;
if (GetTime() - nLastTime < 10 * 60)
// Do this infrequently and randomly to avoid giving away
// that these are our transactions.
static int64 nNextTime;
if (GetTime() < nNextTime)
return;
bool fFirst = (nNextTime == 0);
nNextTime = GetTime() + GetRand(120 * 60);
if (fFirst)
return;
nLastTime = GetTime();
// Rebroadcast any of our txes that aren't in a block yet
printf("RelayWalletTransactions()\n");
printf("ResendWalletTransactions()\n");
CTxDB txdb("r");
CRITICAL_BLOCK(cs_mapWallet)
{
@@ -675,7 +735,10 @@ void RelayWalletTransactions()
foreach(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
{
CWalletTx& wtx = item.second;
mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
// Don't rebroadcast until it's had plenty of time that
// it should have gotten in already by now.
if (nTimeBestReceived - wtx.nTimeReceived > 60 * 60)
mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
}
foreach(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
{
@@ -1169,10 +1232,11 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
}
}
// New best link
// New best block
hashBestChain = hash;
pindexBest = pindexNew;
nBestHeight = pindexBest->nHeight;
nTimeBestReceived = GetTime();
nTransactionsUpdated++;
printf("AddToBlockIndex: new best=%s height=%d\n", hashBestChain.ToString().substr(0,16).c_str(), nBestHeight);
}
@@ -1182,9 +1246,6 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
if (pindexNew == pindexBest)
{
// Relay wallet transactions that haven't gotten in yet
RelayWalletTransactions();
// Notify UI to display prev block's coinbase if it was ours
static uint256 hashPrevBestCoinBase;
CRITICAL_BLOCK(cs_mapWallet)
@@ -1254,11 +1315,10 @@ bool CBlock::AcceptBlock()
if (nTime <= pindexPrev->GetMedianTimePast())
return error("AcceptBlock() : block's timestamp is too early");
// Check that all transactions are finalized (starting around Mar 2010)
if (nBestHeight > 36000)
foreach(const CTransaction& tx, vtx)
if (!tx.IsFinal(nTime))
return error("AcceptBlock() : contains a non-final transaction");
// Check that all transactions are finalized
foreach(const CTransaction& tx, vtx)
if (!tx.IsFinal(nTime))
return error("AcceptBlock() : contains a non-final transaction");
// Check proof of work
if (nBits != GetNextWorkRequired(pindexPrev))
@@ -1274,7 +1334,9 @@ bool CBlock::AcceptBlock()
if (!AddToBlockIndex(nFile, nBlockPos))
return error("AcceptBlock() : AddToBlockIndex failed");
if (hashBestChain == hash && nBestHeight > 28000)
// Don't relay old inventory during initial block download.
// Please keep this number updated to a few thousand below current block count.
if (hashBestChain == hash && nBestHeight > 40000)
RelayInventory(CInv(MSG_BLOCK, hash));
// // Add atoms to user reviews for coins created
@@ -1399,27 +1461,13 @@ bool ScanMessageStart(Stream& s)
bool CheckDiskSpace(int64 nAdditionalBytes)
{
#ifdef __WXMSW__
uint64 nFreeBytesAvailable = 0; // bytes available to caller
uint64 nTotalNumberOfBytes = 0; // bytes on disk
uint64 nTotalNumberOfFreeBytes = 0; // free bytes on disk
if (!GetDiskFreeSpaceEx(GetDataDir().c_str(),
(PULARGE_INTEGER)&nFreeBytesAvailable,
(PULARGE_INTEGER)&nTotalNumberOfBytes,
(PULARGE_INTEGER)&nTotalNumberOfFreeBytes))
{
printf("ERROR: GetDiskFreeSpaceEx() failed\n");
return true;
}
#else
uint64 nFreeBytesAvailable = filesystem::space(GetDataDir()).available;
#endif
// Check for 15MB because database could create another 10MB log file at any time
if (nFreeBytesAvailable < (int64)15000000 + nAdditionalBytes)
{
fShutdown = true;
ThreadSafeMessageBox("Warning: Your disk space is low ", "Bitcoin", wxOK | wxICON_EXCLAMATION);
ThreadSafeMessageBox(_("Warning: Disk space is low "), "Bitcoin", wxOK | wxICON_EXCLAMATION);
CreateThread(Shutdown, NULL);
return false;
}
@@ -1507,9 +1555,11 @@ bool LoadBlockIndex(bool fAllowNew)
CTransaction txNew;
txNew.vin.resize(1);
txNew.vout.resize(1);
txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
txNew.vout[0].nValue = 50 * COIN;
txNew.vout[0].scriptPubKey = CScript() << CBigNum("0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704") << OP_CHECKSIG;
txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
txNew.vout[0].nValue = 50 * COIN;
CBigNum bnPubKey;
bnPubKey.SetHex("0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704");
txNew.vout[0].scriptPubKey = CScript() << bnPubKey << OP_CHECKSIG;
CBlock block;
block.vtx.push_back(txNew);
block.hashPrevBlock = 0;
@@ -1643,10 +1693,8 @@ bool AlreadyHave(CTxDB& txdb, const CInv& inv)
{
switch (inv.type)
{
case MSG_TX: return mapTransactions.count(inv.hash) || txdb.ContainsTx(inv.hash);
case MSG_BLOCK: return mapBlockIndex.count(inv.hash) || mapOrphanBlocks.count(inv.hash);
case MSG_REVIEW: return true;
case MSG_PRODUCT: return mapProducts.count(inv.hash);
case MSG_TX: return mapTransactions.count(inv.hash) || txdb.ContainsTx(inv.hash);
case MSG_BLOCK: return mapBlockIndex.count(inv.hash) || mapOrphanBlocks.count(inv.hash);
}
// Don't know what it is, just say we already got one
return true;
@@ -1734,6 +1782,11 @@ bool ProcessMessages(CNode* pfrom)
// Allow exceptions from underlength message on vRecv
printf("ProcessMessage(%s, %d bytes) : Exception '%s' caught, normally caused by a message being shorter than its stated length\n", strCommand.c_str(), nMessageSize, e.what());
}
else if (strstr(e.what(), ": size too large"))
{
// Allow exceptions from overlong size
printf("ProcessMessage(%s, %d bytes) : Exception '%s' caught\n", strCommand.c_str(), nMessageSize, e.what());
}
else
{
PrintException(&e, "ProcessMessage()");
@@ -1840,7 +1893,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
return error("message addr size() = %d", vAddr.size());
// Store the new addresses
CAddrDB addrdb;
foreach(CAddress& addr, vAddr)
{
if (fShutdown)
@@ -1848,7 +1900,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
addr.nTime = GetAdjustedTime() - 2 * 60 * 60;
if (pfrom->fGetAddr)
addr.nTime -= 5 * 24 * 60 * 60;
AddAddress(addrdb, addr, false);
AddAddress(addr, false);
pfrom->AddAddressKnown(addr);
if (!pfrom->fGetAddr && addr.IsRoutable())
{
@@ -2041,24 +2093,6 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
}
else if (strCommand == "review")
{
CDataStream vMsg(vRecv);
CReview review;
vRecv >> review;
CInv inv(MSG_REVIEW, review.GetHash());
pfrom->AddInventoryKnown(inv);
if (review.AcceptReview())
{
// Relay the original message as-is in case it's a higher version than we know how to parse
RelayMessage(inv, vMsg);
mapAlreadyAskedFor.erase(inv);
}
}
else if (strCommand == "block")
{
auto_ptr<CBlock> pblock(new CBlock);
@@ -2194,7 +2228,7 @@ bool SendMessages(CNode* pto)
return true;
// Keep-alive ping
if (pto->nLastSend && GetTime() - pto->nLastSend > 12 * 60 && pto->vSend.empty())
if (pto->nLastSend && GetTime() - pto->nLastSend > 30 * 60 && pto->vSend.empty())
pto->PushMessage("ping");
// Address refresh broadcast
@@ -2216,60 +2250,81 @@ bool SendMessages(CNode* pto)
}
}
// Delay tx inv messages to protect privacy,
// trickle them out to a few nodes at a time.
bool fSendTxInv = false;
if (GetTimeMillis() - pto->nLastSentTxInv > 1800 + GetRand(200))
{
pto->nLastSentTxInv = GetTimeMillis();
fSendTxInv = true;
}
// Resend wallet transactions that haven't gotten in a block yet
ResendWalletTransactions();
//
// Message: addr
//
vector<CAddress> vAddrToSend;
vAddrToSend.reserve(pto->vAddrToSend.size());
vector<CAddress> vAddr;
vAddr.reserve(pto->vAddrToSend.size());
foreach(const CAddress& addr, pto->vAddrToSend)
{
// returns true if wasn't already contained in the set
if (pto->setAddrKnown.insert(addr).second)
{
vAddrToSend.push_back(addr);
if (vAddrToSend.size() >= 1000)
vAddr.push_back(addr);
if (vAddr.size() >= 1000)
{
pto->PushMessage("addr", vAddrToSend);
vAddrToSend.clear();
pto->PushMessage("addr", vAddr);
vAddr.clear();
}
}
}
pto->vAddrToSend.clear();
if (!vAddrToSend.empty())
pto->PushMessage("addr", vAddrToSend);
if (!vAddr.empty())
pto->PushMessage("addr", vAddr);
//
// Message: inventory
//
vector<CInv> vInventoryToSend;
vector<CInv> vInv;
vector<CInv> vInvWait;
CRITICAL_BLOCK(pto->cs_inventory)
{
vInventoryToSend.reserve(pto->vInventoryToSend.size());
vInv.reserve(pto->vInventoryToSend.size());
vInvWait.reserve(pto->vInventoryToSend.size());
foreach(const CInv& inv, pto->vInventoryToSend)
{
// delay txes
if (!fSendTxInv && inv.type == MSG_TX)
{
vInvWait.push_back(inv);
continue;
}
// returns true if wasn't already contained in the set
if (pto->setInventoryKnown.insert(inv).second)
{
vInventoryToSend.push_back(inv);
if (vInventoryToSend.size() >= 1000)
vInv.push_back(inv);
if (vInv.size() >= 1000)
{
pto->PushMessage("inv", vInventoryToSend);
vInventoryToSend.clear();
pto->PushMessage("inv", vInv);
vInv.clear();
}
}
}
pto->vInventoryToSend.clear();
pto->vInventoryToSend = vInvWait;
}
if (!vInventoryToSend.empty())
pto->PushMessage("inv", vInventoryToSend);
if (!vInv.empty())
pto->PushMessage("inv", vInv);
//
// Message: getdata
//
vector<CInv> vAskFor;
vector<CInv> vGetData;
int64 nNow = GetTime() * 1000000;
CTxDB txdb("r");
while (!pto->mapAskFor.empty() && (*pto->mapAskFor.begin()).first <= nNow)
@@ -2278,17 +2333,17 @@ bool SendMessages(CNode* pto)
if (!AlreadyHave(txdb, inv))
{
printf("sending getdata: %s\n", inv.ToString().c_str());
vAskFor.push_back(inv);
if (vAskFor.size() >= 1000)
vGetData.push_back(inv);
if (vGetData.size() >= 1000)
{
pto->PushMessage("getdata", vAskFor);
vAskFor.clear();
pto->PushMessage("getdata", vGetData);
vGetData.clear();
}
}
pto->mapAskFor.erase(pto->mapAskFor.begin());
}
if (!vAskFor.empty())
pto->PushMessage("getdata", vAskFor);
if (!vGetData.empty())
pto->PushMessage("getdata", vGetData);
}
return true;
@@ -2351,7 +2406,6 @@ void ThreadBitcoinMiner(void* parg)
vnThreadsRunning[3]--;
PrintException(NULL, "ThreadBitcoinMiner()");
}
printf("ThreadBitcoinMiner exiting, %d threads remaining\n", vnThreadsRunning[3]);
}
@@ -2592,7 +2646,12 @@ void BitcoinMiner()
do
{
pindexTmp = pindexBest;
Sleep(10000);
for (int i = 0; i < 10; i++)
{
Sleep(1000);
if (fShutdown)
return;
}
}
while (pindexTmp != pindexBest);
}
@@ -2788,14 +2847,24 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CK
// Fill a vout back to self with any change
if (nValueIn > nTotalValue)
{
// Note: We use a new key here to keep it from being obvious which side is the change.
// The drawback is that by not reusing a previous key, the change may be lost if a
// backup is restored, if the backup doesn't have the new private key for the change.
// If we reused the old key, it would be possible to add code to look for and
// rediscover unknown transactions that were written with keys of ours to recover
// post-backup change.
// New private key
if (keyRet.IsNull())
keyRet.MakeNewKey();
// Fill a vout to ourself
CScript scriptPubKey;
scriptPubKey << keyRet.GetPubKey() << OP_CHECKSIG;
wtxNew.vout.push_back(CTxOut(nValueIn - nTotalValue, scriptPubKey));
// Fill a vout to ourself, using same address type as the payment
CScript scriptChange;
if (scriptPubKey.GetBitcoinAddressHash160() != 0)
scriptChange.SetBitcoinAddress(keyRet.GetPubKey());
else
scriptChange << keyRet.GetPubKey() << OP_CHECKSIG;
wtxNew.vout.push_back(CTxOut(nValueIn - nTotalValue, scriptChange));
}
// Fill a vout to the payee
@@ -2834,38 +2903,50 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CK
}
// Call after CreateTransaction unless you want to abort
bool CommitTransactionSpent(const CWalletTx& wtxNew, const CKey& key)
bool CommitTransaction(CWalletTx& wtxNew, const CKey& key)
{
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_mapWallet)
{
//// todo: eventually should make this transactional, never want to add a
//// transaction without marking spent transactions, although the risk of
//// interruption during this step is remote.
// This is only to keep the database open to defeat the auto-flush for the
// duration of this scope. This is the only place where this optimization
// maybe makes sense; please don't do it anywhere else.
CWalletDB walletdb("r");
// Add the change's private key to wallet
if (!key.IsNull() && !AddKey(key))
throw runtime_error("CommitTransactionSpent() : AddKey failed\n");
// Add tx to wallet, because if it has change it's also ours,
// otherwise just for transaction history.
AddToWallet(wtxNew);
// Mark old coins as spent
set<CWalletTx*> setCoins;
foreach(const CTxIn& txin, wtxNew.vin)
setCoins.insert(&mapWallet[txin.prevout.hash]);
foreach(CWalletTx* pcoin, setCoins)
printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
CRITICAL_BLOCK(cs_mapWallet)
{
pcoin->fSpent = true;
pcoin->WriteToDisk();
vWalletUpdated.push_back(pcoin->GetHash());
// This is only to keep the database open to defeat the auto-flush for the
// duration of this scope. This is the only place where this optimization
// maybe makes sense; please don't do it anywhere else.
CWalletDB walletdb("r");
// Add the change's private key to wallet
if (!key.IsNull() && !AddKey(key))
throw runtime_error("CommitTransaction() : AddKey failed\n");
// Add tx to wallet, because if it has change it's also ours,
// otherwise just for transaction history.
AddToWallet(wtxNew);
// Mark old coins as spent
set<CWalletTx*> setCoins;
foreach(const CTxIn& txin, wtxNew.vin)
setCoins.insert(&mapWallet[txin.prevout.hash]);
foreach(CWalletTx* pcoin, setCoins)
{
pcoin->fSpent = true;
pcoin->WriteToDisk();
vWalletUpdated.push_back(pcoin->GetHash());
}
}
// Track how many getdata requests our transaction gets
CRITICAL_BLOCK(cs_mapRequestCount)
mapRequestCount[wtxNew.GetHash()] = 0;
// Broadcast
if (!wtxNew.AcceptTransaction())
{
// This must not fail. The transaction has already been signed and recorded.
printf("CommitTransaction() : Error: Transaction not valid");
return false;
}
wtxNew.RelayWalletTransaction();
}
MainFrameRepaint();
return true;
@@ -2874,7 +2955,7 @@ bool CommitTransactionSpent(const CWalletTx& wtxNew, const CKey& key)
bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew)
string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
{
CRITICAL_BLOCK(cs_main)
{
@@ -2884,34 +2965,37 @@ bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew)
{
string strError;
if (nValue + nFeeRequired > GetBalance())
strError = strprintf("Error: This is an oversized transaction that requires a transaction fee of %s ", FormatMoney(nFeeRequired).c_str());
strError = strprintf(_("Error: This is an oversized transaction that requires a transaction fee of %s "), FormatMoney(nFeeRequired).c_str());
else
strError = "Error: Transaction creation failed ";
wxMessageBox(strError, "Sending...");
return error("SendMoney() : %s", strError.c_str());
}
if (!CommitTransactionSpent(wtxNew, key))
{
wxMessageBox("Error finalizing transaction ", "Sending...");
return error("SendMoney() : Error finalizing transaction");
strError = _("Error: Transaction creation failed ");
printf("SendMoney() : %s", strError.c_str());
return strError;
}
// Track how many getdata requests our transaction gets
CRITICAL_BLOCK(cs_mapRequestCount)
mapRequestCount[wtxNew.GetHash()] = 0;
if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))
return "ABORTED";
printf("SendMoney: %s\n", wtxNew.GetHash().ToString().substr(0,6).c_str());
// Broadcast
if (!wtxNew.AcceptTransaction())
{
// This must not fail. The transaction has already been signed and recorded.
throw runtime_error("SendMoney() : wtxNew.AcceptTransaction() failed\n");
wxMessageBox("Error: Transaction not valid ", "Sending...");
return error("SendMoney() : Error: Transaction not valid");
}
wtxNew.RelayWalletTransaction();
if (!CommitTransaction(wtxNew, key))
return _("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
}
MainFrameRepaint();
return true;
return "";
}
string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
{
// Check amount
if (nValue <= 0)
return _("Invalid amount");
if (nValue + nTransactionFee > GetBalance())
return _("You don't have enough money");
// Parse bitcoin address
CScript scriptPubKey;
if (!scriptPubKey.SetBitcoinAddress(strAddress))
return _("Invalid bitcoin address");
return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee);
}

44
main.h
View File

@@ -1,4 +1,4 @@
// Copyright (c) 2009 Satoshi Nakamoto
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
@@ -36,6 +36,8 @@ extern CBlockIndex* pindexBest;
extern unsigned int nTransactionsUpdated;
extern map<uint256, int> mapRequestCount;
extern CCriticalSection cs_mapRequestCount;
extern map<string, string> mapAddressBook;
extern CCriticalSection cs_mapAddressBook;
// Settings
extern int fGenerateBitcoins;
@@ -56,8 +58,8 @@ FILE* AppendBlockFile(unsigned int& nFileRet);
bool AddKey(const CKey& key);
vector<unsigned char> GenerateNewKey();
bool AddToWallet(const CWalletTx& wtxIn);
void WalletUpdateSpent(const COutPoint& prevout);
void ReacceptWalletTransactions();
void RelayWalletTransactions();
bool LoadBlockIndex(bool fAllowNew=true);
void PrintBlockTree();
bool ProcessMessages(CNode* pfrom);
@@ -65,8 +67,10 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv);
bool SendMessages(CNode* pto);
int64 GetBalance();
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CKey& keyRet, int64& nFeeRequiredRet);
bool CommitTransactionSpent(const CWalletTx& wtxNew, const CKey& key);
bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew);
bool CommitTransaction(CWalletTx& wtxNew, const CKey& key);
bool BroadcastTransaction(CWalletTx& wtxNew);
string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
void GenerateBitcoins(bool fGenerate);
void ThreadBitcoinMiner(void* parg);
void BitcoinMiner();
@@ -679,7 +683,8 @@ public:
int SetMerkleBranch(const CBlock* pblock=NULL);
int GetDepthInMainChain() const;
int GetDepthInMainChain(int& nHeightRet) const;
int GetDepthInMainChain() const { int nHeight; return GetDepthInMainChain(nHeight); }
bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
int GetBlocksToMaturity() const;
bool AcceptTransaction(CTxDB& txdb, bool fCheckInputs=true);
@@ -1370,6 +1375,35 @@ public:
//
// Private key that includes an expiration date in case it never gets used.
//
class CWalletKey
{
public:
CPrivKey vchPrivKey;
int64 nTimeCreated;
int64 nTimeExpires;
string strComment;
//// todo: add something to note what created it (user, getnewaddress, change)
//// maybe should have a map<string, string> property map
CWalletKey(int64 nTimeExpiresIn=0)
{
nTimeCreated = (nTimeExpiresIn ? GetTime() : 0);
nTimeExpires = nTimeExpiresIn;
}
IMPLEMENT_SERIALIZE
(
if (!(nType & SER_GETHASH))
READWRITE(nVersion);
READWRITE(vchPrivKey);
READWRITE(nTimeCreated);
READWRITE(nTimeExpires);
READWRITE(strComment);
)
};

View File

@@ -1,37 +1,41 @@
# Copyright (c) 2009 Satoshi Nakamoto
# Copyright (c) 2009-2010 Satoshi Nakamoto
# Distributed under the MIT/X11 software license, see the accompanying
# file license.txt or http://www.opensource.org/licenses/mit-license.php.
ifneq "$(BUILD)" "debug"
ifneq "$(BUILD)" "release"
BUILD=debug
endif
endif
ifeq "$(BUILD)" "debug"
D=d
DEBUGFLAGS=-g -D__WXDEBUG__
endif
# for wxWidgets-2.8.x, search and replace "mswud"->"mswd" and "29u"->"28"
INCLUDEPATHS= \
-I"/boost" \
-I"/db/build_unix" \
-I"/openssl/include" \
-I"/wxwidgets/lib/gcc_lib/mswud" \
-I"/wxwidgets/include"
LIBPATHS= \
-L"/boost/stage/lib" \
-L"/db/build_unix" \
-L"/openssl/out" \
-L"/wxwidgets/lib/gcc_lib"
INCLUDEPATHS=-I"/boost" -I"/db/build_unix" -I"/openssl/include" -I"/wxwidgets/lib/vc_lib/mswd" -I"/wxwidgets/include"
LIBPATHS=-L"/db/build_unix" -L"/openssl/out" -L"/wxwidgets/lib/gcc_lib"
LIBS= \
-l libboost_system-mgw34-mt-d -l libboost_filesystem-mgw34-mt-d \
-l db_cxx \
-l eay32 \
-l wxmsw28$(D)_richtext -l wxmsw28$(D)_html -l wxmsw28$(D)_core -l wxmsw28$(D)_adv -l wxbase28$(D) -l wxtiff$(D) -l wxjpeg$(D) -l wxpng$(D) -l wxzlib$(D) -l wxregex$(D) -l wxexpat$(D) \
-l wxmsw29ud_html -l wxmsw29ud_core -l wxmsw29ud_adv -l wxbase29ud -l wxtiffd -l wxjpegd -l wxpngd -l wxzlibd \
-l kernel32 -l user32 -l gdi32 -l comdlg32 -l winspool -l winmm -l shell32 -l comctl32 -l ole32 -l oleaut32 -l uuid -l rpcrt4 -l advapi32 -l ws2_32 -l shlwapi
WXDEFS=-DWIN32 -D__WXMSW__ -D_WINDOWS -DNOPCH
DEBUGFLAGS=-g -D__WXDEBUG__
CFLAGS=-mthreads -O0 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
HEADERS=headers.h util.h main.h serialize.h uint256.h key.h bignum.h script.h db.h base58.h
HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h
all: bitcoin.exe
headers.h.gch: headers.h $(HEADERS) net.h irc.h market.h uibase.h ui.h
headers.h.gch: headers.h $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/util.o: util.cpp $(HEADERS)
@@ -40,19 +44,16 @@ obj/util.o: util.cpp $(HEADERS)
obj/script.o: script.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/db.o: db.cpp $(HEADERS) market.h
obj/db.o: db.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/net.o: net.cpp $(HEADERS) net.h
obj/net.o: net.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/main.o: main.cpp $(HEADERS) net.h market.h sha.h
obj/main.o: main.cpp $(HEADERS) sha.h
g++ -c $(CFLAGS) -o $@ $<
obj/market.o: market.cpp $(HEADERS) market.h
g++ -c $(CFLAGS) -o $@ $<
obj/ui.o: ui.cpp $(HEADERS) net.h uibase.h ui.h market.h
obj/ui.o: ui.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/uibase.o: uibase.cpp uibase.h
@@ -64,13 +65,17 @@ obj/sha.o: sha.cpp sha.h
obj/irc.o: irc.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/rpc.o: rpc.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/ui_res.o: ui.rc rc/bitcoin.ico rc/check.ico rc/send16.bmp rc/send16mask.bmp rc/send16masknoshadow.bmp rc/send20.bmp rc/send20mask.bmp rc/addressbook16.bmp rc/addressbook16mask.bmp rc/addressbook20.bmp rc/addressbook20mask.bmp
windres $(WXDEFS) $(INCLUDEPATHS) -o $@ -i $<
OBJS=obj/util.o obj/script.o obj/db.o obj/net.o obj/main.o obj/market.o \
obj/ui.o obj/uibase.o obj/sha.o obj/irc.o obj/ui_res.o
OBJS=obj/util.o obj/script.o obj/db.o obj/net.o obj/main.o \
obj/ui.o obj/uibase.o obj/sha.o obj/irc.o obj/rpc.o \
obj/ui_res.o
bitcoin.exe: headers.h.gch $(OBJS)
-kill /f bitcoin.exe

View File

@@ -1,24 +1,13 @@
# Copyright (c) 2009 Satoshi Nakamoto
# Copyright (c) 2009-2010 Satoshi Nakamoto
# Distributed under the MIT/X11 software license, see the accompanying
# file license.txt or http://www.opensource.org/licenses/mit-license.php.
ifneq "$(BUILD)" "debug"
ifneq "$(BUILD)" "release"
BUILD=debug
endif
endif
ifeq "$(BUILD)" "debug"
D=d
DEBUGFLAGS=-g -D__WXDEBUG__
endif
INCLUDEPATHS= \
-I"/usr/include" \
-I"/usr/local/include/wx-2.8" \
-I"/usr/local/lib/wx/include/gtk2-ansi-debug-static-2.8"
-I"/usr/local/include/wx-2.9" \
-I"/usr/local/lib/wx/include/gtk2-unicode-debug-static-2.9"
LIBPATHS= \
-L"/usr/lib" \
@@ -26,23 +15,24 @@ LIBPATHS= \
LIBS= \
-Wl,-Bstatic \
-l boost_system -l boost_filesystem \
-l boost_system-mt -l boost_filesystem-mt \
-l db_cxx \
-l wx_gtk2$(D)-2.8 \
-l wx_gtk2ud-2.9 \
-Wl,-Bdynamic \
-l crypto \
-l gtk-x11-2.0 -l gthread-2.0 -l SM
WXDEFS=-D__WXGTK__ -DNOPCH
DEBUGFLAGS=-g -D__WXDEBUG__
CFLAGS=-O0 -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
HEADERS=headers.h util.h main.h serialize.h uint256.h key.h bignum.h script.h db.h base58.h
HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h
all: bitcoin
headers.h.gch: headers.h $(HEADERS) net.h irc.h market.h uibase.h ui.h
headers.h.gch: headers.h $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/util.o: util.cpp $(HEADERS)
@@ -51,19 +41,16 @@ obj/util.o: util.cpp $(HEADERS)
obj/script.o: script.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/db.o: db.cpp $(HEADERS) market.h
obj/db.o: db.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/net.o: net.cpp $(HEADERS) net.h
obj/net.o: net.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/main.o: main.cpp $(HEADERS) net.h market.h sha.h
obj/main.o: main.cpp $(HEADERS) sha.h
g++ -c $(CFLAGS) -o $@ $<
obj/market.o: market.cpp $(HEADERS) market.h
g++ -c $(CFLAGS) -o $@ $<
obj/ui.o: ui.cpp $(HEADERS) net.h uibase.h ui.h market.h
obj/ui.o: ui.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/uibase.o: uibase.cpp uibase.h
@@ -75,11 +62,13 @@ obj/sha.o: sha.cpp sha.h
obj/irc.o: irc.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
obj/rpc.o: rpc.cpp $(HEADERS)
g++ -c $(CFLAGS) -o $@ $<
OBJS=obj/util.o obj/script.o obj/db.o obj/net.o obj/main.o obj/market.o \
obj/ui.o obj/uibase.o obj/sha.o obj/irc.o
OBJS=obj/util.o obj/script.o obj/db.o obj/net.o obj/main.o \
obj/ui.o obj/uibase.o obj/sha.o obj/irc.o obj/rpc.o
bitcoin: headers.h.gch $(OBJS)
g++ $(CFLAGS) -o $@ $(LIBPATHS) $(OBJS) $(LIBS)

View File

@@ -1,28 +1,34 @@
# Copyright (c) 2009 Satoshi Nakamoto
# Copyright (c) 2009-2010 Satoshi Nakamoto
# Distributed under the MIT/X11 software license, see the accompanying
# file license.txt or http://www.opensource.org/licenses/mit-license.php.
!IF "$(BUILD)" != "debug" && "$(BUILD)" != "release"
BUILD=debug
!ENDIF
!IF "$(BUILD)" == "debug"
D=d
DEBUGFLAGS=/Zi /Od /D__WXDEBUG__
!ENDIF
# for wxWidgets-2.8.x, search and replace "mswud"->"mswd" and "29u"->"28"
INCLUDEPATHS= \
/I"/boost" \
/I"/db/build_windows" \
/I"/openssl/include" \
/I"/wxwidgets/lib/vc_lib/mswud" \
/I"/wxwidgets/include"
LIBPATHS= \
/LIBPATH:"/boost/stage/lib" \
/LIBPATH:"/db/build_windows/debug" \
/LIBPATH:"/openssl/out" \
/LIBPATH:"/wxwidgets/lib/vc_lib"
INCLUDEPATHS=/I"/boost" /I"/db/build_windows" /I"/openssl/include" /I"/wxwidgets/lib/vc_lib/mswd" /I"/wxwidgets/include"
LIBPATHS=/LIBPATH:"/db/build_windows/$(BUILD)" /LIBPATH:"/openssl/out" /LIBPATH:"/wxwidgets/lib/vc_lib"
LIBS= \
libdb47s$(D).lib \
libeay32.lib \
wxmsw28$(D)_richtext.lib wxmsw28$(D)_html.lib wxmsw28$(D)_core.lib wxmsw28$(D)_adv.lib wxbase28$(D).lib wxtiff$(D).lib wxjpeg$(D).lib wxpng$(D).lib wxzlib$(D).lib wxregex$(D).lib wxexpat$(D).lib \
kernel32.lib user32.lib gdi32.lib comdlg32.lib winspool.lib winmm.lib shell32.lib comctl32.lib ole32.lib oleaut32.lib uuid.lib rpcrt4.lib advapi32.lib ws2_32.lib shlwapi.lib
libboost_system-vc80-mt-gd.lib libboost_filesystem-vc80-mt-gd.lib \
libdb47sd.lib \
libeay32.lib \
wxmsw29ud_html.lib wxmsw29ud_core.lib wxmsw29ud_adv.lib wxbase29ud.lib wxtiffd.lib wxjpegd.lib wxpngd.lib wxzlibd.lib \
kernel32.lib user32.lib gdi32.lib comdlg32.lib winspool.lib winmm.lib shell32.lib comctl32.lib ole32.lib oleaut32.lib uuid.lib rpcrt4.lib advapi32.lib ws2_32.lib shlwapi.lib
WXDEFS=/DWIN32 /D__WXMSW__ /D_WINDOWS /DNOPCH
CFLAGS=/c /nologo /Ob0 /MD$(D) /EHsc /GR /Zm300 /YX /Fpobj/headers.pch $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
HEADERS=headers.h util.h main.h serialize.h uint256.h key.h bignum.h script.h db.h base58.h
DEBUGFLAGS=/Zi /Od /D__WXDEBUG__
CFLAGS=/c /nologo /Ob0 /MDd /EHsc /GR /Zm300 $(DEBUGFLAGS) $(WXDEFS) $(INCLUDEPATHS)
HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h
@@ -35,37 +41,38 @@ obj\util.obj: util.cpp $(HEADERS)
obj\script.obj: script.cpp $(HEADERS)
cl $(CFLAGS) /Fo$@ %s
obj\db.obj: db.cpp $(HEADERS) market.h
obj\db.obj: db.cpp $(HEADERS)
cl $(CFLAGS) /Fo$@ %s
obj\net.obj: net.cpp $(HEADERS) net.h
obj\net.obj: net.cpp $(HEADERS)
cl $(CFLAGS) /Fo$@ %s
obj\main.obj: main.cpp $(HEADERS) net.h market.h
obj\main.obj: main.cpp $(HEADERS) sha.h
cl $(CFLAGS) /Fo$@ %s
obj\market.obj: market.cpp $(HEADERS) market.h
cl $(CFLAGS) /Fo$@ %s
obj\ui.obj: ui.cpp $(HEADERS) net.h uibase.h ui.h market.h
obj\ui.obj: ui.cpp $(HEADERS)
cl $(CFLAGS) /Fo$@ %s
obj\uibase.obj: uibase.cpp uibase.h
cl $(CFLAGS) /Fo$@ %s
obj\sha.obj: sha.cpp sha.h
obj\sha.obj: sha.cpp sha.h
cl $(CFLAGS) /O2 /Fo$@ %s
obj\irc.obj: irc.cpp $(HEADERS)
cl $(CFLAGS) /Fo$@ %s
obj\rpc.obj: rpc.cpp $(HEADERS)
cl $(CFLAGS) /Fo$@ %s
obj\ui.res: ui.rc rc/bitcoin.ico rc/check.ico rc/send16.bmp rc/send16mask.bmp rc/send16masknoshadow.bmp rc/send20.bmp rc/send20mask.bmp rc/addressbook16.bmp rc/addressbook16mask.bmp rc/addressbook20.bmp rc/addressbook20mask.bmp
rc $(INCLUDEPATHS) $(WXDEFS) /Fo$@ %s
OBJS=obj\util.obj obj\script.obj obj\db.obj obj\net.obj obj\main.obj obj\market.obj \
obj\ui.obj obj\uibase.obj obj\sha.obj obj\irc.obj obj\ui.res
OBJS=obj\util.obj obj\script.obj obj\db.obj obj\net.obj obj\main.obj \
obj\ui.obj obj\uibase.obj obj\sha.obj obj\irc.obj obj\rpc.obj \
obj\ui.res
bitcoin.exe: $(OBJS)
-kill /f bitcoin.exe & sleep 1

View File

@@ -1,264 +0,0 @@
// Copyright (c) 2009 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
#include "headers.h"
//
// Global state variables
//
//// later figure out how these are persisted
map<uint256, CProduct> mapMyProducts;
map<uint256, CProduct> mapProducts;
CCriticalSection cs_mapProducts;
bool AdvertInsert(const CProduct& product)
{
uint256 hash = product.GetHash();
bool fNew = false;
bool fUpdated = false;
CRITICAL_BLOCK(cs_mapProducts)
{
// Insert or find existing product
pair<map<uint256, CProduct>::iterator, bool> item = mapProducts.insert(make_pair(hash, product));
CProduct* pproduct = &(*(item.first)).second;
fNew = item.second;
// Update if newer
if (product.nSequence > pproduct->nSequence)
{
*pproduct = product;
fUpdated = true;
}
}
//if (fNew)
// NotifyProductAdded(hash);
//else if (fUpdated)
// NotifyProductUpdated(hash);
return (fNew || fUpdated);
}
void AdvertErase(const CProduct& product)
{
uint256 hash = product.GetHash();
CRITICAL_BLOCK(cs_mapProducts)
mapProducts.erase(hash);
//NotifyProductDeleted(hash);
}
template<typename T>
unsigned int Union(T& v1, T& v2)
{
// v1 = v1 union v2
// v1 and v2 must be sorted
// returns the number of elements added to v1
///// need to check that this is equivalent, then delete this comment
//vector<unsigned short> vUnion(v1.size() + v2.size());
//vUnion.erase(set_union(v1.begin(), v1.end(),
// v2.begin(), v2.end(),
// vUnion.begin()),
// vUnion.end());
T vUnion;
vUnion.reserve(v1.size() + v2.size());
set_union(v1.begin(), v1.end(),
v2.begin(), v2.end(),
back_inserter(vUnion));
unsigned int nAdded = vUnion.size() - v1.size();
if (nAdded > 0)
v1 = vUnion;
return nAdded;
}
void CUser::AddAtom(unsigned short nAtom, bool fOrigin)
{
// Ignore duplicates
if (binary_search(vAtomsIn.begin(), vAtomsIn.end(), nAtom) ||
find(vAtomsNew.begin(), vAtomsNew.end(), nAtom) != vAtomsNew.end())
return;
//// instead of zero atom, should change to free atom that propagates,
//// limited to lower than a certain value like 5 so conflicts quickly
// The zero atom never propagates,
// new atoms always propagate through the user that created them
if (nAtom == 0 || fOrigin)
{
vector<unsigned short> vTmp(1, nAtom);
Union(vAtomsIn, vTmp);
if (fOrigin)
vAtomsOut.push_back(nAtom);
return;
}
vAtomsNew.push_back(nAtom);
if (vAtomsNew.size() >= nFlowthroughRate || vAtomsOut.empty())
{
// Select atom to flow through to vAtomsOut
vAtomsOut.push_back(vAtomsNew[GetRand(vAtomsNew.size())]);
// Merge vAtomsNew into vAtomsIn
sort(vAtomsNew.begin(), vAtomsNew.end());
Union(vAtomsIn, vAtomsNew);
vAtomsNew.clear();
}
}
bool AddAtomsAndPropagate(uint256 hashUserStart, const vector<unsigned short>& vAtoms, bool fOrigin)
{
CReviewDB reviewdb;
map<uint256, vector<unsigned short> > pmapPropagate[2];
pmapPropagate[0][hashUserStart] = vAtoms;
for (int side = 0; !pmapPropagate[side].empty(); side = 1 - side)
{
map<uint256, vector<unsigned short> >& mapFrom = pmapPropagate[side];
map<uint256, vector<unsigned short> >& mapTo = pmapPropagate[1 - side];
for (map<uint256, vector<unsigned short> >::iterator mi = mapFrom.begin(); mi != mapFrom.end(); ++mi)
{
const uint256& hashUser = (*mi).first;
const vector<unsigned short>& vReceived = (*mi).second;
///// this would be a lot easier on the database if it put the new atom at the beginning of the list,
///// so the change would be right next to the vector size.
// Read user
CUser user;
reviewdb.ReadUser(hashUser, user);
unsigned int nIn = user.vAtomsIn.size();
unsigned int nNew = user.vAtomsNew.size();
unsigned int nOut = user.vAtomsOut.size();
// Add atoms received
foreach(unsigned short nAtom, vReceived)
user.AddAtom(nAtom, fOrigin);
fOrigin = false;
// Don't bother writing to disk if no changes
if (user.vAtomsIn.size() == nIn && user.vAtomsNew.size() == nNew)
continue;
// Propagate
if (user.vAtomsOut.size() > nOut)
foreach(const uint256& hash, user.vLinksOut)
mapTo[hash].insert(mapTo[hash].end(), user.vAtomsOut.begin() + nOut, user.vAtomsOut.end());
// Write back
if (!reviewdb.WriteUser(hashUser, user))
return false;
}
mapFrom.clear();
}
return true;
}
bool CReview::AcceptReview()
{
// Timestamp
nTime = GetTime();
// Check signature
if (!CKey::Verify(vchPubKeyFrom, GetSigHash(), vchSig))
return false;
CReviewDB reviewdb;
// Add review text to recipient
vector<CReview> vReviews;
reviewdb.ReadReviews(hashTo, vReviews);
vReviews.push_back(*this);
if (!reviewdb.WriteReviews(hashTo, vReviews))
return false;
// Add link from sender
CUser user;
uint256 hashFrom = Hash(vchPubKeyFrom.begin(), vchPubKeyFrom.end());
reviewdb.ReadUser(hashFrom, user);
user.vLinksOut.push_back(hashTo);
if (!reviewdb.WriteUser(hashFrom, user))
return false;
reviewdb.Close();
// Propagate atoms to recipient
vector<unsigned short> vZeroAtom(1, 0);
if (!AddAtomsAndPropagate(hashTo, user.vAtomsOut.size() ? user.vAtomsOut : vZeroAtom, false))
return false;
return true;
}
bool CProduct::CheckSignature()
{
return (CKey::Verify(vchPubKeyFrom, GetSigHash(), vchSig));
}
bool CProduct::CheckProduct()
{
if (!CheckSignature())
return false;
// Make sure it's a summary product
if (!mapDetails.empty() || !vOrderForm.empty())
return false;
// Look up seller's atom count
CReviewDB reviewdb("r");
CUser user;
reviewdb.ReadUser(GetUserHash(), user);
nAtoms = user.GetAtomCount();
reviewdb.Close();
////// delme, this is now done by AdvertInsert
//// Store to memory
//CRITICAL_BLOCK(cs_mapProducts)
// mapProducts[GetHash()] = *this;
return true;
}

182
market.h
View File

@@ -1,182 +0,0 @@
// Copyright (c) 2009 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
class CUser;
class CReview;
class CProduct;
static const unsigned int nFlowthroughRate = 2;
bool AdvertInsert(const CProduct& product);
void AdvertErase(const CProduct& product);
bool AddAtomsAndPropagate(uint256 hashUserStart, const vector<unsigned short>& vAtoms, bool fOrigin);
class CUser
{
public:
vector<unsigned short> vAtomsIn;
vector<unsigned short> vAtomsNew;
vector<unsigned short> vAtomsOut;
vector<uint256> vLinksOut;
CUser()
{
}
IMPLEMENT_SERIALIZE
(
if (!(nType & SER_GETHASH))
READWRITE(nVersion);
READWRITE(vAtomsIn);
READWRITE(vAtomsNew);
READWRITE(vAtomsOut);
READWRITE(vLinksOut);
)
void SetNull()
{
vAtomsIn.clear();
vAtomsNew.clear();
vAtomsOut.clear();
vLinksOut.clear();
}
uint256 GetHash() const { return SerializeHash(*this); }
int GetAtomCount() const
{
return (vAtomsIn.size() + vAtomsNew.size());
}
void AddAtom(unsigned short nAtom, bool fOrigin);
};
class CReview
{
public:
int nVersion;
uint256 hashTo;
map<string, string> mapValue;
vector<unsigned char> vchPubKeyFrom;
vector<unsigned char> vchSig;
// memory only
unsigned int nTime;
int nAtoms;
CReview()
{
nVersion = 1;
hashTo = 0;
nTime = 0;
nAtoms = 0;
}
IMPLEMENT_SERIALIZE
(
READWRITE(this->nVersion);
nVersion = this->nVersion;
if (!(nType & SER_DISK))
READWRITE(hashTo);
READWRITE(mapValue);
READWRITE(vchPubKeyFrom);
if (!(nType & SER_GETHASH))
READWRITE(vchSig);
)
uint256 GetHash() const { return SerializeHash(*this); }
uint256 GetSigHash() const { return SerializeHash(*this, SER_GETHASH|SER_SKIPSIG); }
uint256 GetUserHash() const { return Hash(vchPubKeyFrom.begin(), vchPubKeyFrom.end()); }
bool AcceptReview();
};
class CProduct
{
public:
int nVersion;
CAddress addr;
map<string, string> mapValue;
map<string, string> mapDetails;
vector<pair<string, string> > vOrderForm;
unsigned int nSequence;
vector<unsigned char> vchPubKeyFrom;
vector<unsigned char> vchSig;
// disk only
int nAtoms;
// memory only
set<unsigned int> setSources;
CProduct()
{
nVersion = 1;
nAtoms = 0;
nSequence = 0;
}
IMPLEMENT_SERIALIZE
(
READWRITE(this->nVersion);
nVersion = this->nVersion;
READWRITE(addr);
READWRITE(mapValue);
if (!(nType & SER_GETHASH))
{
READWRITE(mapDetails);
READWRITE(vOrderForm);
READWRITE(nSequence);
}
READWRITE(vchPubKeyFrom);
if (!(nType & SER_GETHASH))
READWRITE(vchSig);
if (nType & SER_DISK)
READWRITE(nAtoms);
)
uint256 GetHash() const { return SerializeHash(*this); }
uint256 GetSigHash() const { return SerializeHash(*this, SER_GETHASH|SER_SKIPSIG); }
uint256 GetUserHash() const { return Hash(vchPubKeyFrom.begin(), vchPubKeyFrom.end()); }
bool CheckSignature();
bool CheckProduct();
};
extern map<uint256, CProduct> mapProducts;
extern CCriticalSection cs_mapProducts;
extern map<uint256, CProduct> mapMyProducts;

40
net.cpp
View File

@@ -1,4 +1,4 @@
// Copyright (c) 2009 Satoshi Nakamoto
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
@@ -223,7 +223,7 @@ bool GetMyExternalIP(unsigned int& ipRet)
bool AddAddress(CAddrDB& addrdb, CAddress addr, bool fCurrentlyOnline)
bool AddAddress(CAddress addr, bool fCurrentlyOnline)
{
if (!addr.IsRoutable())
return false;
@@ -239,7 +239,7 @@ bool AddAddress(CAddrDB& addrdb, CAddress addr, bool fCurrentlyOnline)
// New address
printf("AddAddress(%s)\n", addr.ToStringLog().c_str());
mapAddresses.insert(make_pair(addr.GetKey(), addr));
addrdb.WriteAddress(addr);
CAddrDB().WriteAddress(addr);
return true;
}
else
@@ -260,7 +260,7 @@ bool AddAddress(CAddrDB& addrdb, CAddress addr, bool fCurrentlyOnline)
fUpdated = true;
}
if (fUpdated)
addrdb.WriteAddress(addrFound);
CAddrDB().WriteAddress(addrFound);
}
}
return false;
@@ -381,11 +381,6 @@ void CNode::CancelSubscribe(unsigned int nChannel)
foreach(CNode* pnode, vNodes)
if (pnode != this)
pnode->PushMessage("sub-cancel", nChannel);
// Clear memory, no longer subscribed
if (nChannel == MSG_PRODUCT)
CRITICAL_BLOCK(cs_mapProducts)
mapProducts.clear();
}
}
@@ -497,10 +492,6 @@ void CNode::Cleanup()
// All of a nodes broadcasts and subscriptions are automatically torn down
// when it goes down, so a node has to stay up to keep its broadcast going.
CRITICAL_BLOCK(cs_mapProducts)
for (map<uint256, CProduct>::iterator mi = mapProducts.begin(); mi != mapProducts.end();)
AdvertRemoveSource(this, MSG_PRODUCT, 0, (*(mi++)).second);
// Cancel subscriptions
for (unsigned int nChannel = 0; nChannel < vfSubscribe.size(); nChannel++)
if (vfSubscribe[nChannel])
@@ -522,7 +513,6 @@ void CNode::Cleanup()
void ThreadSocketHandler(void* parg)
{
IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
try
{
vnThreadsRunning[0]++;
@@ -536,7 +526,6 @@ void ThreadSocketHandler(void* parg)
vnThreadsRunning[0]--;
throw; // support pthread_cancel()
}
printf("ThreadSocketHandler exiting\n");
}
@@ -657,11 +646,7 @@ void ThreadSocketHandler2(void* parg)
if (FD_ISSET(hListenSocket, &fdsetRecv))
{
struct sockaddr_in sockaddr;
#ifdef __WXMSW__
int len = sizeof(sockaddr);
#else
socklen_t len = sizeof(sockaddr);
#endif
SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
CAddress addr(sockaddr);
if (hSocket == INVALID_SOCKET)
@@ -816,7 +801,6 @@ void ThreadSocketHandler2(void* parg)
void ThreadOpenConnections(void* parg)
{
IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
try
{
vnThreadsRunning[1]++;
@@ -830,7 +814,6 @@ void ThreadOpenConnections(void* parg)
vnThreadsRunning[1]--;
PrintException(NULL, "ThreadOpenConnections()");
}
printf("ThreadOpenConnections exiting\n");
}
@@ -881,11 +864,11 @@ void ThreadOpenConnections2(void* parg)
vnThreadsRunning[1]--;
Sleep(500);
const int nMaxConnections = 15;
while (vNodes.size() >= nMaxConnections || vNodes.size() >= mapAddresses.size())
while (vNodes.size() >= nMaxConnections)
{
Sleep(2000);
if (fShutdown)
return;
Sleep(2000);
}
vnThreadsRunning[1]++;
if (fShutdown)
@@ -928,7 +911,7 @@ void ThreadOpenConnections2(void* parg)
// 30 days 27 hours
// 90 days 46 hours
// 365 days 93 hours
int64 nDelay = (int64)(3600.0 * sqrt(fabs(nSinceLastSeen) / 3600.0) + nRandomizer);
int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer);
// Fast reconnect for one hour after last seen
if (nSinceLastSeen < 60 * 60)
@@ -1016,7 +999,6 @@ bool OpenNetworkConnection(const CAddress& addrConnect)
void ThreadMessageHandler(void* parg)
{
IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
try
{
vnThreadsRunning[2]++;
@@ -1030,7 +1012,6 @@ void ThreadMessageHandler(void* parg)
vnThreadsRunning[2]--;
PrintException(NULL, "ThreadMessageHandler()");
}
printf("ThreadMessageHandler exiting\n");
}
@@ -1038,7 +1019,7 @@ void ThreadMessageHandler2(void* parg)
{
printf("ThreadMessageHandler started\n");
SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
loop
while (!fShutdown)
{
// Poll the connected nodes for messages
vector<CNode*> vNodesCopy;
@@ -1329,7 +1310,7 @@ bool StopNode()
fShutdown = true;
nTransactionsUpdated++;
int64 nStart = GetTime();
while (vnThreadsRunning[0] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0)
while (vnThreadsRunning[0] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0)
{
if (GetTime() - nStart > 20)
break;
@@ -1339,7 +1320,8 @@ bool StopNode()
if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
while (vnThreadsRunning[2] > 0)
if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
Sleep(20);
Sleep(50);

13
net.h
View File

@@ -1,4 +1,4 @@
// Copyright (c) 2009 Satoshi Nakamoto
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
@@ -23,7 +23,7 @@ enum
bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet);
bool GetMyExternalIP(unsigned int& ipRet);
bool AddAddress(CAddrDB& addrdb, CAddress addr, bool fCurrentlyOnline=true);
bool AddAddress(CAddress addr, bool fCurrentlyOnline=true);
void AddressCurrentlyConnected(const CAddress& addr);
CNode* FindNode(unsigned int ip);
CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0);
@@ -341,9 +341,6 @@ enum
{
MSG_TX = 1,
MSG_BLOCK,
MSG_REVIEW,
MSG_PRODUCT,
MSG_TABLE,
};
static const char* ppszTypeName[] =
@@ -351,9 +348,6 @@ static const char* ppszTypeName[] =
"ERROR",
"tx",
"block",
"review",
"product",
"table",
};
class CInv
@@ -518,6 +512,7 @@ public:
vector<CInv> vInventoryToSend;
CCriticalSection cs_inventory;
multimap<int64, CInv> mapAskFor;
int64 nLastSentTxInv;
// publish and subscription
vector<char> vfSubscribe;
@@ -627,7 +622,7 @@ public:
// We're using mapAskFor as a priority queue,
// the key is the earliest time the request can be sent
int64& nRequestTime = mapAlreadyAskedFor[inv];
printf("askfor %s %"PRI64d"\n", inv.ToString().c_str(), nRequestTime);
printf("askfor %s %"PRI64d"\n", inv.ToString().c_str(), nRequestTime);
// Make sure not to reuse time indexes to keep things in the same order
int64 nNow = (GetTime() - 1) * 1000000;

733
rpc.cpp Normal file
View File

@@ -0,0 +1,733 @@
// Copyright (c) 2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
#include "headers.h"
#undef printf
#include <boost/asio.hpp>
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_writer_template.h"
#include "json/json_spirit_utils.h"
#define printf OutputDebugStringF
// MinGW 3.4.5 gets "fatal error: had to relocate PCH" if the json headers are
// precompiled in headers.h. The problem might be when the pch file goes over
// a certain size around 145MB. If we need access to json_spirit outside this
// file, we could use the compiled json_spirit option.
using boost::asio::ip::tcp;
using namespace json_spirit;
void ThreadRPCServer2(void* parg);
///
/// Note: I'm not finished designing this interface, it's still subject to change.
///
Value stop(const Array& params)
{
if (params.size() != 0)
throw runtime_error(
"stop (no parameters)\n"
"Stop bitcoin server.");
// Shutdown will take long enough that the response should get back
CreateThread(Shutdown, NULL);
return "bitcoin server stopping";
}
Value getblockcount(const Array& params)
{
if (params.size() != 0)
throw runtime_error(
"getblockcount (no parameters)\n"
"Returns the number of blocks in the longest block chain.");
return nBestHeight + 1;
}
Value getblocknumber(const Array& params)
{
if (params.size() != 0)
throw runtime_error(
"getblocknumber (no parameters)\n"
"Returns the block number of the latest block in the longest block chain.");
return nBestHeight;
}
Value getconnectioncount(const Array& params)
{
if (params.size() != 0)
throw runtime_error(
"getconnectioncount (no parameters)\n"
"Returns the number of connections to other nodes.");
return (int)vNodes.size();
}
Value getdifficulty(const Array& params)
{
if (params.size() != 0)
throw runtime_error(
"getdifficulty (no parameters)\n"
"Returns the proof-of-work difficulty as a multiple of the minimum difficulty.");
if (pindexBest == NULL)
throw runtime_error("block chain not loaded");
// Floating point number that is a multiple of the minimum difficulty,
// minimum difficulty = 1.0.
int nShift = 256 - 32 - 31; // to fit in a uint
double dMinimum = (CBigNum().SetCompact(bnProofOfWorkLimit.GetCompact()) >> nShift).getuint();
double dCurrently = (CBigNum().SetCompact(pindexBest->nBits) >> nShift).getuint();
return dMinimum / dCurrently;
}
Value getbalance(const Array& params)
{
if (params.size() != 0)
throw runtime_error(
"getbalance (no parameters)\n"
"Returns the server's available balance.");
return ((double)GetBalance() / (double)COIN);
}
Value getgenerate(const Array& params)
{
if (params.size() != 0)
throw runtime_error(
"getgenerate (no parameters)\n"
"Returns true or false.");
return (bool)fGenerateBitcoins;
}
Value setgenerate(const Array& params)
{
if (params.size() < 1 || params.size() > 2)
throw runtime_error(
"setgenerate <generate> [genproclimit]\n"
"<generate> is true or false to turn generation on or off.\n"
"Generation is limited to [genproclimit] processors, -1 is unlimited.");
bool fGenerate = true;
if (params.size() > 0)
fGenerate = params[0].get_bool();
if (params.size() > 1)
{
int nGenProcLimit = params[1].get_int();
fLimitProcessors = (nGenProcLimit != -1);
CWalletDB().WriteSetting("fLimitProcessors", fLimitProcessors);
if (nGenProcLimit != -1)
CWalletDB().WriteSetting("nLimitProcessors", nLimitProcessors = nGenProcLimit);
}
GenerateBitcoins(fGenerate);
return Value::null;
}
Value getinfo(const Array& params)
{
if (params.size() != 0)
throw runtime_error(
"getinfo (no parameters)");
Object obj;
obj.push_back(Pair("balance", (double)GetBalance() / (double)COIN));
obj.push_back(Pair("blocks", (int)nBestHeight + 1));
obj.push_back(Pair("connections", (int)vNodes.size()));
obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string())));
obj.push_back(Pair("generate", (bool)fGenerateBitcoins));
obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1)));
return obj;
}
Value getnewaddress(const Array& params)
{
if (params.size() > 1)
throw runtime_error(
"getnewaddress [label]\n"
"Returns a new bitcoin address for receiving payments. "
"If [label] is specified (recommended), it is added to the address book "
"so payments received with the address will be labeled.");
// Parse the label first so we don't generate a key if there's an error
string strLabel;
if (params.size() > 0)
strLabel = params[0].get_str();
// Generate a new key that is added to wallet
string strAddress = PubKeyToAddress(GenerateNewKey());
SetAddressBookName(strAddress, strLabel);
return strAddress;
}
Value sendtoaddress(const Array& params)
{
if (params.size() < 2 || params.size() > 4)
throw runtime_error(
"sendtoaddress <bitcoinaddress> <amount> [comment] [comment-to]\n"
"<amount> is a real and is rounded to the nearest 0.01");
string strAddress = params[0].get_str();
// Amount
if (params[1].get_real() <= 0.0 || params[1].get_real() > 21000000.0)
throw runtime_error("Invalid amount");
int64 nAmount = roundint64(params[1].get_real() * 100.00) * CENT;
// Wallet comments
CWalletTx wtx;
if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
wtx.mapValue["message"] = params[2].get_str();
if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
wtx.mapValue["to"] = params[3].get_str();
string strError = SendMoneyToBitcoinAddress(strAddress, nAmount, wtx);
if (strError != "")
throw runtime_error(strError);
return "sent";
}
Value listtransactions(const Array& params)
{
if (params.size() > 2)
throw runtime_error(
"listtransactions [count=10] [includegenerated=false]\n"
"Returns up to [count] most recent transactions.");
int64 nCount = 10;
if (params.size() > 0)
nCount = params[0].get_int64();
bool fGenerated = false;
if (params.size() > 1)
fGenerated = params[1].get_bool();
Array ret;
//// not finished
ret.push_back("not implemented yet");
return ret;
}
Value getamountreceived(const Array& params)
{
if (params.size() < 1 || params.size() > 2)
throw runtime_error(
"getamountreceived <bitcoinaddress> [minconf=1]\n"
"Returns the total amount received by <bitcoinaddress> in transactions with at least [minconf] confirmations.");
// Bitcoin address
string strAddress = params[0].get_str();
CScript scriptPubKey;
if (!scriptPubKey.SetBitcoinAddress(strAddress))
throw runtime_error("Invalid bitcoin address");
// Minimum confirmations
int nMinDepth = 1;
if (params.size() > 1)
nMinDepth = params[1].get_int();
// Tally
int64 nAmount = 0;
CRITICAL_BLOCK(cs_mapWallet)
{
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
if (wtx.IsCoinBase() || !wtx.IsFinal())
continue;
foreach(const CTxOut& txout, wtx.vout)
if (txout.scriptPubKey == scriptPubKey)
if (wtx.GetDepthInMainChain() >= nMinDepth)
nAmount += txout.nValue;
}
}
return (double)nAmount / (double)COIN;
}
struct tallyitem
{
int64 nAmount;
int nConf;
tallyitem()
{
nAmount = 0;
nConf = INT_MAX;
}
};
Value getallreceived(const Array& params)
{
if (params.size() > 1)
throw runtime_error(
"getallreceived [minconf=1]\n"
"[minconf] is the minimum number of confirmations before payments are included.\n"
"Returns an array of objects containing:\n"
" \"address\" : receiving address\n"
" \"amount\" : total amount received by the address\n"
" \"confirmations\" : number of confirmations of the most recent transaction included\n"
" \"label\" : the label of the receiving address");
// Minimum confirmations
int nMinDepth = 1;
if (params.size() > 0)
nMinDepth = params[0].get_int();
// Tally
map<uint160, tallyitem> mapTally;
CRITICAL_BLOCK(cs_mapWallet)
{
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx& wtx = (*it).second;
if (wtx.IsCoinBase() || !wtx.IsFinal())
continue;
int nDepth = wtx.GetDepthInMainChain();
if (nDepth < nMinDepth)
continue;
// Filter out debits and payments to self, which may have change return
// we don't want to count.
int64 nCredit = wtx.GetCredit(true);
int64 nDebit = wtx.GetDebit();
int64 nNet = nCredit - nDebit;
if (nNet <= 0)
continue;
foreach(const CTxOut& txout, wtx.vout)
{
uint160 hash160 = txout.scriptPubKey.GetBitcoinAddressHash160();
if (hash160 == 0 || !mapPubKeys.count(hash160))
continue;
tallyitem& item = mapTally[hash160];
item.nAmount += txout.nValue;
item.nConf = min(item.nConf, nDepth);
}
}
}
// Reply
Array ret;
CRITICAL_BLOCK(cs_mapAddressBook)
{
for (map<uint160, tallyitem>::iterator it = mapTally.begin(); it != mapTally.end(); ++it)
{
string strAddress = Hash160ToAddress((*it).first);
string strLabel;
map<string, string>::iterator mi = mapAddressBook.find(strAddress);
if (mi != mapAddressBook.end())
strLabel = (*mi).second;
Object obj;
obj.push_back(Pair("address", strAddress));
obj.push_back(Pair("amount", (double)(*it).second.nAmount / (double)COIN));
obj.push_back(Pair("confirmations", (*it).second.nConf));
obj.push_back(Pair("label", strLabel));
ret.push_back(obj);
}
}
return ret;
}
//
// Call Table
//
typedef Value(*rpcfn_type)(const Array& params);
pair<string, rpcfn_type> pCallTable[] =
{
make_pair("stop", &stop),
make_pair("getblockcount", &getblockcount),
make_pair("getblocknumber", &getblocknumber),
make_pair("getconnectioncount", &getconnectioncount),
make_pair("getdifficulty", &getdifficulty),
make_pair("getbalance", &getbalance),
make_pair("getgenerate", &getgenerate),
make_pair("setgenerate", &setgenerate),
make_pair("getinfo", &getinfo),
make_pair("getnewaddress", &getnewaddress),
make_pair("sendtoaddress", &sendtoaddress),
make_pair("listtransactions", &listtransactions),
make_pair("getamountreceived", &getamountreceived),
make_pair("getallreceived", &getallreceived),
};
map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
//
// HTTP protocol
//
// This ain't Apache. We're just using HTTP header for the length field
// and to be compatible with other JSON-RPC implementations.
//
string HTTPPost(const string& strMsg)
{
return strprintf(
"POST / HTTP/1.1\r\n"
"User-Agent: json-rpc/1.0\r\n"
"Host: 127.0.0.1\r\n"
"Content-Type: application/json\r\n"
"Content-Length: %d\r\n"
"Accept: application/json\r\n"
"\r\n"
"%s",
strMsg.size(),
strMsg.c_str());
}
string HTTPReply(const string& strMsg, int nStatus=200)
{
string strStatus;
if (nStatus == 200) strStatus = "OK";
if (nStatus == 500) strStatus = "Internal Server Error";
return strprintf(
"HTTP/1.1 %d %s\r\n"
"Connection: close\r\n"
"Content-Length: %d\r\n"
"Content-Type: application/json\r\n"
"Date: Sat, 08 Jul 2006 12:04:08 GMT\r\n"
"Server: json-rpc/1.0\r\n"
"\r\n"
"%s",
nStatus,
strStatus.c_str(),
strMsg.size(),
strMsg.c_str());
}
int ReadHTTPHeader(tcp::iostream& stream)
{
int nLen = 0;
loop
{
string str;
std::getline(stream, str);
if (str.empty() || str == "\r")
break;
if (str.substr(0,15) == "Content-Length:")
nLen = atoi(str.substr(15));
}
return nLen;
}
inline string ReadHTTP(tcp::iostream& stream)
{
// Read header
int nLen = ReadHTTPHeader(stream);
if (nLen <= 0)
return string();
// Read message
vector<char> vch(nLen);
stream.read(&vch[0], nLen);
return string(vch.begin(), vch.end());
}
//
// JSON-RPC protocol
//
// http://json-rpc.org/wiki/specification
// http://www.codeproject.com/KB/recipes/JSON_Spirit.aspx
//
string JSONRPCRequest(const string& strMethod, const Array& params, const Value& id)
{
Object request;
request.push_back(Pair("method", strMethod));
request.push_back(Pair("params", params));
request.push_back(Pair("id", id));
return write_string(Value(request), false) + "\n";
}
string JSONRPCReply(const Value& result, const Value& error, const Value& id)
{
Object reply;
if (error.type() != null_type)
reply.push_back(Pair("result", Value::null));
else
reply.push_back(Pair("result", result));
reply.push_back(Pair("error", error));
reply.push_back(Pair("id", id));
return write_string(Value(reply), false) + "\n";
}
void ThreadRPCServer(void* parg)
{
IMPLEMENT_RANDOMIZE_STACK(ThreadRPCServer(parg));
try
{
vnThreadsRunning[4]++;
ThreadRPCServer2(parg);
vnThreadsRunning[4]--;
}
catch (std::exception& e) {
vnThreadsRunning[4]--;
PrintException(&e, "ThreadRPCServer()");
} catch (...) {
vnThreadsRunning[4]--;
PrintException(NULL, "ThreadRPCServer()");
}
printf("ThreadRPCServer exiting\n");
}
void ThreadRPCServer2(void* parg)
{
printf("ThreadRPCServer started\n");
// Bind to loopback 127.0.0.1 so the socket can only be accessed locally
boost::asio::io_service io_service;
tcp::endpoint endpoint(boost::asio::ip::address_v4::loopback(), 8332);
tcp::acceptor acceptor(io_service, endpoint);
loop
{
// Accept connection
tcp::iostream stream;
tcp::endpoint peer;
vnThreadsRunning[4]--;
acceptor.accept(*stream.rdbuf(), peer);
vnThreadsRunning[4]++;
if (fShutdown)
return;
// Shouldn't be possible for anyone else to connect, but just in case
if (peer.address().to_string() != "127.0.0.1")
continue;
// Receive request
string strRequest = ReadHTTP(stream);
printf("ThreadRPCServer request=%s", strRequest.c_str());
// Handle multiple invocations per request
string::iterator begin = strRequest.begin();
while (skipspaces(begin), begin != strRequest.end())
{
string::iterator prev = begin;
Value id;
try
{
// Parse request
Value valRequest;
if (!read_range(begin, strRequest.end(), valRequest))
throw runtime_error("Parse error.");
const Object& request = valRequest.get_obj();
if (find_value(request, "method").type() != str_type ||
find_value(request, "params").type() != array_type)
throw runtime_error("Invalid request.");
string strMethod = find_value(request, "method").get_str();
const Array& params = find_value(request, "params").get_array();
id = find_value(request, "id");
// Execute
map<string, rpcfn_type>::iterator mi = mapCallTable.find(strMethod);
if (mi == mapCallTable.end())
throw runtime_error("Method not found.");
Value result = (*(*mi).second)(params);
// Send reply
string strReply = JSONRPCReply(result, Value::null, id);
stream << HTTPReply(strReply, 200) << std::flush;
}
catch (std::exception& e)
{
// Send error reply
string strReply = JSONRPCReply(Value::null, e.what(), id);
stream << HTTPReply(strReply, 500) << std::flush;
}
if (begin == prev)
break;
}
}
}
Value CallRPC(const string& strMethod, const Array& params)
{
// Connect to localhost
tcp::iostream stream("127.0.0.1", "8332");
if (stream.fail())
throw runtime_error("couldn't connect to server");
// Send request
string strRequest = JSONRPCRequest(strMethod, params, 1);
stream << HTTPPost(strRequest) << std::flush;
// Receive reply
string strReply = ReadHTTP(stream);
if (strReply.empty())
throw runtime_error("no response from server");
// Parse reply
Value valReply;
if (!read_string(strReply, valReply))
throw runtime_error("couldn't parse reply from server");
const Object& reply = valReply.get_obj();
if (reply.empty())
throw runtime_error("expected reply to have result, error and id properties");
const Value& result = find_value(reply, "result");
const Value& error = find_value(reply, "error");
const Value& id = find_value(reply, "id");
if (error.type() == str_type)
throw runtime_error(error.get_str());
else if (error.type() != null_type)
throw runtime_error(write_string(error, false));
return result;
}
template<typename T>
void ConvertTo(Value& value)
{
if (value.type() == str_type)
{
// reinterpret string as unquoted json value
Value value2;
if (!read_string(value.get_str(), value2))
throw runtime_error("type mismatch");
value = value2.get_value<T>();
}
else
{
value = value.get_value<T>();
}
}
int CommandLineRPC(int argc, char *argv[])
{
try
{
// Check that method exists
if (argc < 2)
throw runtime_error("too few parameters");
string strMethod = argv[1];
if (!mapCallTable.count(strMethod))
throw runtime_error(strprintf("unknown command: %s", strMethod.c_str()));
// Parameters default to strings
Array params;
for (int i = 2; i < argc; i++)
params.push_back(argv[i]);
int n = params.size();
//
// Special case other types
//
if (strMethod == "setgenerate" && n > 0) ConvertTo<bool>(params[0]);
if (strMethod == "setgenerate" && n > 1) ConvertTo<boost::int64_t>(params[1]);
if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
if (strMethod == "listtransactions" && n > 0) ConvertTo<boost::int64_t>(params[0]);
if (strMethod == "listtransactions" && n > 1) ConvertTo<bool>(params[1]);
if (strMethod == "getamountreceived" && n > 1) ConvertTo<boost::int64_t>(params[1]);
if (strMethod == "getallreceived" && n > 0) ConvertTo<boost::int64_t>(params[0]);
// Execute
Value result = CallRPC(strMethod, params);
// Print result
string strResult = (result.type() == str_type ? result.get_str() : write_string(result, true));
if (result.type() != null_type)
{
if (fWindows)
// Windows GUI apps can't print to command line,
// so for now settle for a message box yuck
wxMessageBox(strResult.c_str(), "Bitcoin", wxOK);
else
fprintf(stdout, "%s\n", strResult.c_str());
}
return 0;
}
catch (std::exception& e) {
if (fWindows)
wxMessageBox(strprintf("error: %s\n", e.what()).c_str(), "Bitcoin", wxOK);
else
fprintf(stderr, "error: %s\n", e.what());
} catch (...) {
PrintException(NULL, "CommandLineRPC()");
}
return 1;
}
#ifdef TEST
int main(int argc, char *argv[])
{
#ifdef _MSC_VER
// Turn off microsoft heap dump noise
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_WARN, CreateFile("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0));
#endif
setbuf(stdin, NULL);
setbuf(stdout, NULL);
setbuf(stderr, NULL);
try
{
if (argc >= 2 && string(argv[1]) == "-server")
{
printf("server ready\n");
ThreadRPCServer(NULL);
}
else
{
return CommandLineRPC(argc, argv);
}
}
catch (std::exception& e) {
PrintException(&e, "main()");
} catch (...) {
PrintException(NULL, "main()");
}
return 0;
}
#endif

6
rpc.h Normal file
View File

@@ -0,0 +1,6 @@
// Copyright (c) 2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
void ThreadRPCServer(void* parg);
int CommandLineRPC(int argc, char *argv[]);

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2009 Satoshi Nakamoto
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
@@ -660,7 +660,7 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI
if (stack.size() < 1)
return false;
valtype& vch = stacktop(-1);
valtype vchHash(opcode == OP_RIPEMD160 || opcode == OP_SHA1 || opcode == OP_HASH160 ? 20 : 32);
valtype vchHash((opcode == OP_RIPEMD160 || opcode == OP_SHA1 || opcode == OP_HASH160) ? 20 : 32);
if (opcode == OP_RIPEMD160)
RIPEMD160(&vch[0], vch.size(), &vchHash[0]);
else if (opcode == OP_SHA1)
@@ -753,9 +753,9 @@ bool EvalScript(const CScript& script, const CTransaction& txTo, unsigned int nI
CScript scriptCode(pbegincodehash, pend);
// Drop the signatures, since there's no way for a signature to sign itself
for (int i = 0; i < nSigsCount; i++)
for (int k = 0; k < nSigsCount; k++)
{
valtype& vchSig = stacktop(-isig-i);
valtype& vchSig = stacktop(-isig-k);
scriptCode.FindAndDelete(CScript(vchSig));
}
@@ -909,7 +909,6 @@ bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CSc
bool Solver(const CScript& scriptPubKey, vector<pair<opcodetype, valtype> >& vSolutionRet)
{
// Templates
@@ -919,7 +918,7 @@ bool Solver(const CScript& scriptPubKey, vector<pair<opcodetype, valtype> >& vSo
// Standard tx, sender provides pubkey, receiver adds signature
vTemplates.push_back(CScript() << OP_PUBKEY << OP_CHECKSIG);
// Short account number tx, sender provides hash of pubkey, receiver provides signature and pubkey
// Bitcoin address tx, sender provides hash of pubkey, receiver provides signature and pubkey
vTemplates.push_back(CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG);
}
@@ -1123,5 +1122,13 @@ bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsig
if (txin.prevout.hash != txFrom.GetHash())
return false;
return EvalScript(txin.scriptSig + CScript(OP_CODESEPARATOR) + txout.scriptPubKey, txTo, nIn, nHashType);
if (!EvalScript(txin.scriptSig + CScript(OP_CODESEPARATOR) + txout.scriptPubKey, txTo, nIn, nHashType))
return false;
// Anytime a signature is successfully verified, it's proof the outpoint is spent,
// so lets update the wallet spent flag if it doesn't know due to wallet.dat being
// restored from backup or the user making copies of wallet.dat.
WalletUpdateSpent(txin.prevout);
return true;
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2009 Satoshi Nakamoto
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
@@ -472,7 +472,7 @@ public:
bool GetOp(iterator& pc, opcodetype& opcodeRet, vector<unsigned char>& vchRet)
{
// This is why people hate C++
// Wrapper so it can be called with either iterator or const_iterator
const_iterator pc2 = pc;
bool fRet = GetOp(pc2, opcodeRet, vchRet);
pc = begin() + (pc2 - begin());
@@ -551,6 +551,51 @@ public:
}
uint160 GetBitcoinAddressHash160() const
{
opcodetype opcode;
vector<unsigned char> vch;
CScript::const_iterator pc = begin();
if (!GetOp(pc, opcode, vch) || opcode != OP_DUP) return 0;
if (!GetOp(pc, opcode, vch) || opcode != OP_HASH160) return 0;
if (!GetOp(pc, opcode, vch) || vch.size() != sizeof(uint160)) return 0;
uint160 hash160 = uint160(vch);
if (!GetOp(pc, opcode, vch) || opcode != OP_EQUALVERIFY) return 0;
if (!GetOp(pc, opcode, vch) || opcode != OP_CHECKSIG) return 0;
if (pc != end()) return 0;
return hash160;
}
string GetBitcoinAddress() const
{
uint160 hash160 = GetBitcoinAddressHash160();
if (hash160 == 0)
return "";
return Hash160ToAddress(hash160);
}
void SetBitcoinAddress(const uint160& hash160)
{
this->clear();
*this << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG;
}
void SetBitcoinAddress(const vector<unsigned char>& vchPubKey)
{
SetBitcoinAddress(Hash160(vchPubKey));
}
bool SetBitcoinAddress(const string& strAddress)
{
this->clear();
uint160 hash160;
if (!AddressToHash160(strAddress, hash160))
return false;
SetBitcoinAddress(hash160);
return true;
}
void PrintHex() const
{
printf("CScript(%s)\n", HexStr(begin(), end()).c_str());

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2009 Satoshi Nakamoto
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
@@ -19,8 +19,8 @@ class CScript;
class CDataStream;
class CAutoFile;
static const int VERSION = 200;
static const char* pszSubVer = " rc2";
static const int VERSION = 206;
static const char* pszSubVer = ".0";
@@ -194,28 +194,32 @@ uint64 ReadCompactSize(Stream& is)
{
unsigned char chSize;
READDATA(is, chSize);
uint64 nSizeRet = 0;
if (chSize < UCHAR_MAX-2)
{
return chSize;
nSizeRet = chSize;
}
else if (chSize == UCHAR_MAX-2)
{
unsigned short nSize;
READDATA(is, nSize);
return nSize;
nSizeRet = nSize;
}
else if (chSize == UCHAR_MAX-1)
{
unsigned int nSize;
READDATA(is, nSize);
return nSize;
nSizeRet = nSize;
}
else
{
uint64 nSize;
READDATA(is, nSize);
return nSize;
nSizeRet = nSize;
}
if (nSizeRet > (uint64)INT_MAX)
throw std::ios_base::failure("ReadCompactSize() : size too large");
return nSizeRet;
}
@@ -460,7 +464,7 @@ void Unserialize_impl(Stream& is, std::vector<T, A>& v, int nType, int nVersion,
unsigned int i = 0;
while (i < nSize)
{
unsigned int blk = min(nSize - i, 1 + 4999999 / sizeof(T));
unsigned int blk = min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T)));
v.resize(i + blk);
is.read((char*)&v[i], blk * sizeof(T));
i += blk;

2415
ui.cpp

File diff suppressed because it is too large Load Diff

230
ui.h
View File

@@ -1,33 +1,25 @@
// Copyright (c) 2009 Satoshi Nakamoto
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
DECLARE_EVENT_TYPE(wxEVT_UITHREADCALL, -1)
DECLARE_EVENT_TYPE(wxEVT_REPLY1, -1)
DECLARE_EVENT_TYPE(wxEVT_REPLY2, -1)
DECLARE_EVENT_TYPE(wxEVT_REPLY3, -1)
extern map<string, string> mapArgs;
// Settings
extern int fShowGenerated;
extern int fMinimizeToTray;
extern int fMinimizeOnClose;
extern void HandleCtrlA(wxKeyEvent& event);
extern string FormatTxStatus(const CWalletTx& wtx);
extern void UIThreadCall(boost::function0<void>);
extern void MainFrameRepaint();
extern void Shutdown(void* parg);
extern int ThreadSafeMessageBox(const string& message, const string& caption="Message", int style=wxOK, wxWindow* parent=NULL, int x=-1, int y=-1);
void HandleCtrlA(wxKeyEvent& event);
string FormatTxStatus(const CWalletTx& wtx);
void UIThreadCall(boost::function0<void>);
void MainFrameRepaint();
void Shutdown(void* parg);
int ThreadSafeMessageBox(const string& message, const string& caption="Message", int style=wxOK, wxWindow* parent=NULL, int x=-1, int y=-1);
bool ThreadSafeAskFee(int64 nFeeRequired, const string& strCaption, wxWindow* parent);
@@ -38,6 +30,7 @@ class CMainFrame : public CMainFrameBase
{
protected:
// Event handlers
void OnNotebookPageChanged(wxNotebookEvent& event);
void OnClose(wxCloseEvent& event);
void OnIconize(wxIconizeEvent& event);
void OnMouseEvents(wxMouseEvent& event);
@@ -46,8 +39,6 @@ protected:
void OnPaint(wxPaintEvent& event);
void OnPaintListCtrl(wxPaintEvent& event);
void OnMenuFileExit(wxCommandEvent& event);
void OnMenuViewShowGenerated(wxCommandEvent& event);
void OnUpdateUIViewShowGenerated(wxUpdateUIEvent& event);
void OnMenuOptionsGenerate(wxCommandEvent& event);
void OnUpdateUIOptionsGenerate(wxUpdateUIEvent& event);
void OnMenuOptionsChangeYourAddress(wxCommandEvent& event);
@@ -57,10 +48,10 @@ protected:
void OnButtonAddressBook(wxCommandEvent& event);
void OnSetFocusAddress(wxFocusEvent& event);
void OnMouseEventsAddress(wxMouseEvent& event);
void OnButtonNew(wxCommandEvent& event);
void OnButtonCopy(wxCommandEvent& event);
void OnButtonChange(wxCommandEvent& event);
void OnListColBeginDrag(wxListEvent& event);
void OnListItemActivatedAllTransactions(wxListEvent& event);
void OnListItemActivated(wxListEvent& event);
void OnListItemActivatedProductsSent(wxListEvent& event);
void OnListItemActivatedOrdersSent(wxListEvent& event);
void OnListItemActivatedOrdersReceived(wxListEvent& event);
@@ -71,6 +62,18 @@ public:
~CMainFrame();
// Custom
enum
{
ALL = 0,
SENTRECEIVED = 1,
SENT = 2,
RECEIVED = 3,
};
int nPage;
wxListCtrl* m_listCtrl;
bool fShowGenerated;
bool fShowSent;
bool fShowReceived;
bool fRefreshListCtrl;
bool fRefreshListCtrlRunning;
bool fOnSetFocusAddress;
@@ -211,190 +214,44 @@ void SendingDialogOnReply3(void* parg, CDataStream& vRecv);
class CYourAddressDialog : public CYourAddressDialogBase
{
protected:
// Event handlers
void OnListEndLabelEdit(wxListEvent& event);
void OnListItemSelected(wxListEvent& event);
void OnListItemActivated(wxListEvent& event);
void OnButtonRename(wxCommandEvent& event);
void OnButtonNew(wxCommandEvent& event);
void OnButtonCopy(wxCommandEvent& event);
void OnButtonOK(wxCommandEvent& event);
void OnButtonCancel(wxCommandEvent& event);
void OnClose(wxCloseEvent& event);
public:
/** Constructor */
CYourAddressDialog(wxWindow* parent);
CYourAddressDialog(wxWindow* parent, const string& strInitSelected);
// Custom
wxString GetAddress();
};
class CAddressBookDialog : public CAddressBookDialogBase
{
protected:
// Event handlers
void OnNotebookPageChanged(wxNotebookEvent& event);
void OnListEndLabelEdit(wxListEvent& event);
void OnListItemSelected(wxListEvent& event);
void OnListItemActivated(wxListEvent& event);
void OnButtonEdit(wxCommandEvent& event);
void OnButtonDelete(wxCommandEvent& event);
void OnButtonNew(wxCommandEvent& event);
void OnButtonCopy(wxCommandEvent& event);
void OnButtonEdit(wxCommandEvent& event);
void OnButtonNew(wxCommandEvent& event);
void OnButtonOK(wxCommandEvent& event);
void OnButtonCancel(wxCommandEvent& event);
void OnClose(wxCloseEvent& event);
public:
/** Constructor */
CAddressBookDialog(wxWindow* parent, const wxString& strInitSelected, bool fSendingIn);
CAddressBookDialog(wxWindow* parent, const wxString& strInitSelected, int nPageIn, bool fDuringSendIn);
// Custom
bool fSending;
enum
{
SENDING = 0,
RECEIVING = 1,
};
int nPage;
wxListCtrl* m_listCtrl;
bool fDuringSend;
wxString GetAddress();
wxString GetSelectedAddress();
wxString GetSelectedSendingAddress();
wxString GetSelectedReceivingAddress();
bool CheckIfMine(const string& strAddress, const string& strTitle);
};
class CProductsDialog : public CProductsDialogBase
{
protected:
// Event handlers
void OnKeyDown(wxKeyEvent& event) { HandleCtrlA(event); }
void OnCombobox(wxCommandEvent& event);
void OnButtonSearch(wxCommandEvent& event);
void OnListItemActivated(wxListEvent& event);
public:
/** Constructor */
CProductsDialog(wxWindow* parent);
// Custom
vector<CProduct> m_vProduct;
};
class CEditProductDialog : public CEditProductDialogBase
{
protected:
// Event handlers
void OnKeyDown(wxKeyEvent& event) { HandleCtrlA(event); }
void OnButtonDel0(wxCommandEvent& event);
void OnButtonDel1(wxCommandEvent& event);
void OnButtonDel2(wxCommandEvent& event);
void OnButtonDel3(wxCommandEvent& event);
void OnButtonDel4(wxCommandEvent& event);
void OnButtonDel5(wxCommandEvent& event);
void OnButtonDel6(wxCommandEvent& event);
void OnButtonDel7(wxCommandEvent& event);
void OnButtonDel8(wxCommandEvent& event);
void OnButtonDel9(wxCommandEvent& event);
void OnButtonDel10(wxCommandEvent& event);
void OnButtonDel11(wxCommandEvent& event);
void OnButtonDel12(wxCommandEvent& event);
void OnButtonDel13(wxCommandEvent& event);
void OnButtonDel14(wxCommandEvent& event);
void OnButtonDel15(wxCommandEvent& event);
void OnButtonDel16(wxCommandEvent& event);
void OnButtonDel17(wxCommandEvent& event);
void OnButtonDel18(wxCommandEvent& event);
void OnButtonDel19(wxCommandEvent& event);
void OnButtonAddField(wxCommandEvent& event);
void OnButtonSend(wxCommandEvent& event);
void OnButtonPreview(wxCommandEvent& event);
void OnButtonCancel(wxCommandEvent& event);
public:
/** Constructor */
CEditProductDialog(wxWindow* parent);
// Custom
enum { FIELDS_MAX = 20 };
wxTextCtrl* m_textCtrlLabel[FIELDS_MAX];
wxTextCtrl* m_textCtrlField[FIELDS_MAX];
wxButton* m_buttonDel[FIELDS_MAX];
void LayoutAll();
void ShowLine(int i, bool fShow=true);
void OnButtonDel(wxCommandEvent& event, int n);
void SetProduct(const CProduct& productIn);
void GetProduct(CProduct& product);
};
class CViewProductDialog : public CViewProductDialogBase
{
protected:
// Event handlers
void OnButtonSubmitForm(wxCommandEvent& event);
void OnButtonCancelForm(wxCommandEvent& event);
void OnButtonBack(wxCommandEvent& event);
void OnButtonNext(wxCommandEvent& event);
void OnButtonCancel(wxCommandEvent& event);
public:
/** Constructor */
CViewProductDialog(wxWindow* parent, const CProduct& productIn);
~CViewProductDialog();
// Custom
CProduct product;
enum { FIELDS_MAX = 20 };
wxStaticText* m_staticTextLabel[FIELDS_MAX];
wxTextCtrl* m_textCtrlField[FIELDS_MAX];
wxChoice* m_choiceField[FIELDS_MAX];
void GetOrder(CWalletTx& order);
void UpdateProductDisplay(bool fDetails);
void OnReply1(wxCommandEvent& event);
};
class CViewOrderDialog : public CViewOrderDialogBase
{
protected:
// Event handlers
void OnButtonOK(wxCommandEvent& event);
public:
/** Constructor */
CViewOrderDialog(wxWindow* parent, CWalletTx order, bool fReceived);
// Custom
bool fReceived;
};
class CEditReviewDialog : public CEditReviewDialogBase
{
protected:
// Event handlers
void OnKeyDown(wxKeyEvent& event) { HandleCtrlA(event); }
void OnButtonSubmit(wxCommandEvent& event);
void OnButtonCancel(wxCommandEvent& event);
public:
/** Constructor */
CEditReviewDialog(wxWindow* parent);
// Custom
void GetReview(CReview& review);
};
class CGetTextFromUserDialog : public CGetTextFromUserDialogBase
{
protected:
@@ -420,16 +277,25 @@ public:
const string& strMessage2="",
const string& strValue2="") : CGetTextFromUserDialogBase(parent, wxID_ANY, strCaption)
{
int x = GetSize().GetWidth();
int y = GetSize().GetHeight();
m_staticTextMessage1->SetLabel(strMessage1);
m_textCtrl1->SetValue(strValue1);
y += wxString(strMessage1).Freq('\n') * 14;
if (!strMessage2.empty())
{
m_staticTextMessage2->Show(true);
m_staticTextMessage2->SetLabel(strMessage2);
m_textCtrl2->Show(true);
m_textCtrl2->SetValue(strValue2);
SetSize(wxDefaultCoord, 180);
y += 46 + wxString(strMessage2).Freq('\n') * 14;
}
if (!fWindows)
{
x *= 1.14;
y *= 1.14;
}
SetSize(x, y);
}
// Custom

1130
uibase.cpp

File diff suppressed because it is too large Load Diff

374
uibase.h
View File

@@ -8,6 +8,8 @@
#ifndef __uibase__
#define __uibase__
#include <wx/intl.h>
#include <wx/string.h>
#include <wx/bitmap.h>
#include <wx/image.h>
@@ -35,60 +37,34 @@
#include <wx/spinctrl.h>
#include <wx/scrolwin.h>
#include <wx/statbmp.h>
#include <wx/combobox.h>
#include <wx/richtext/richtextctrl.h>
///////////////////////////////////////////////////////////////////////////
#define wxID_MAINFRAME 1000
#define wxID_VIEWSHOWGENERATED 1001
#define wxID_OPTIONSGENERATEBITCOINS 1002
#define wxID_MENUOPTIONSOPTIONS 1003
#define wxID_BUTTONSEND 1004
#define wxID_BUTTONRECEIVE 1005
#define wxID_TEXTCTRLADDRESS 1006
#define wxID_OPTIONSGENERATEBITCOINS 1001
#define wxID_MENUOPTIONSOPTIONS 1002
#define wxID_BUTTONSEND 1003
#define wxID_BUTTONRECEIVE 1004
#define wxID_TEXTCTRLADDRESS 1005
#define wxID_BUTTONNEW 1006
#define wxID_BUTTONCOPY 1007
#define wxID_BUTTONCHANGE 1008
#define wxID_TRANSACTIONFEE 1009
#define wxID_PROXYIP 1010
#define wxID_PROXYPORT 1011
#define wxID_TEXTCTRLPAYTO 1012
#define wxID_BUTTONPASTE 1013
#define wxID_BUTTONADDRESSBOOK 1014
#define wxID_TEXTCTRLAMOUNT 1015
#define wxID_CHOICETRANSFERTYPE 1016
#define wxID_LISTCTRL 1017
#define wxID_BUTTONRENAME 1018
#define wxID_BUTTONNEW 1019
#define wxID_BUTTONEDIT 1020
#define wxID_BUTTONDELETE 1021
#define wxID_DEL0 1022
#define wxID_DEL1 1023
#define wxID_DEL2 1024
#define wxID_DEL3 1025
#define wxID_DEL4 1026
#define wxID_DEL5 1027
#define wxID_DEL6 1028
#define wxID_DEL7 1029
#define wxID_DEL8 1030
#define wxID_DEL9 1031
#define wxID_DEL10 1032
#define wxID_DEL11 1033
#define wxID_DEL12 1034
#define wxID_DEL13 1035
#define wxID_DEL14 1036
#define wxID_DEL15 1037
#define wxID_DEL16 1038
#define wxID_DEL17 1039
#define wxID_DEL18 1040
#define wxID_DEL19 1041
#define wxID_BUTTONPREVIEW 1042
#define wxID_BUTTONSAMPLE 1043
#define wxID_CANCEL2 1044
#define wxID_BUTTONBACK 1045
#define wxID_BUTTONNEXT 1046
#define wxID_SUBMIT 1047
#define wxID_TEXTCTRL 1048
#define wxID_TRANSACTIONFEE 1008
#define wxID_PROXYIP 1009
#define wxID_PROXYPORT 1010
#define wxID_TEXTCTRLPAYTO 1011
#define wxID_BUTTONPASTE 1012
#define wxID_BUTTONADDRESSBOOK 1013
#define wxID_TEXTCTRLAMOUNT 1014
#define wxID_CHOICETRANSFERTYPE 1015
#define wxID_LISTCTRL 1016
#define wxID_BUTTONRENAME 1017
#define wxID_PANELSENDING 1018
#define wxID_LISTCTRLSENDING 1019
#define wxID_PANELRECEIVING 1020
#define wxID_LISTCTRLRECEIVING 1021
#define wxID_BUTTONDELETE 1022
#define wxID_BUTTONEDIT 1023
#define wxID_TEXTCTRL 1024
///////////////////////////////////////////////////////////////////////////////
/// Class CMainFrameBase
@@ -100,15 +76,13 @@ class CMainFrameBase : public wxFrame
protected:
wxMenuBar* m_menubar;
wxMenu* m_menuFile;
wxMenu* m_menuView;
wxMenu* m_menuHelp;
wxToolBar* m_toolBar;
wxStatusBar* m_statusBar;
wxStaticText* m_staticText32;
wxTextCtrl* m_textCtrlAddress;
wxButton* m_buttonNew;
wxButton* m_buttonCopy;
wxButton* m_button91;
wxPanel* m_panel14;
wxStaticText* m_staticText41;
@@ -116,11 +90,10 @@ class CMainFrameBase : public wxFrame
wxChoice* m_choiceFilter;
wxNotebook* m_notebook;
wxPanel* m_panel7;
wxPanel* m_panel9;
wxPanel* m_panel8;
wxPanel* m_panel10;
wxPanel* m_panel11;
wxPanel* m_panel91;
wxPanel* m_panel92;
wxPanel* m_panel93;
// Virtual event handlers, overide them in your derived class
virtual void OnClose( wxCloseEvent& event ){ event.Skip(); }
@@ -129,8 +102,6 @@ class CMainFrameBase : public wxFrame
virtual void OnMouseEvents( wxMouseEvent& event ){ event.Skip(); }
virtual void OnPaint( wxPaintEvent& event ){ event.Skip(); }
virtual void OnMenuFileExit( wxCommandEvent& event ){ event.Skip(); }
virtual void OnMenuViewShowGenerated( wxCommandEvent& event ){ event.Skip(); }
virtual void OnUpdateUIViewShowGenerated( wxUpdateUIEvent& event ){ event.Skip(); }
virtual void OnMenuOptionsGenerate( wxCommandEvent& event ){ event.Skip(); }
virtual void OnUpdateUIOptionsGenerate( wxUpdateUIEvent& event ){ event.Skip(); }
virtual void OnMenuOptionsChangeYourAddress( wxCommandEvent& event ){ event.Skip(); }
@@ -141,24 +112,22 @@ class CMainFrameBase : public wxFrame
virtual void OnKeyDown( wxKeyEvent& event ){ event.Skip(); }
virtual void OnMouseEventsAddress( wxMouseEvent& event ){ event.Skip(); }
virtual void OnSetFocusAddress( wxFocusEvent& event ){ event.Skip(); }
virtual void OnButtonNew( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonCopy( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonChange( wxCommandEvent& event ){ event.Skip(); }
virtual void OnNotebookPageChanged( wxNotebookEvent& event ){ event.Skip(); }
virtual void OnListColBeginDrag( wxListEvent& event ){ event.Skip(); }
virtual void OnListItemActivatedAllTransactions( wxListEvent& event ){ event.Skip(); }
virtual void OnListItemActivated( wxListEvent& event ){ event.Skip(); }
virtual void OnPaintListCtrl( wxPaintEvent& event ){ event.Skip(); }
virtual void OnListItemActivatedOrdersSent( wxListEvent& event ){ event.Skip(); }
virtual void OnListItemActivatedProductsSent( wxListEvent& event ){ event.Skip(); }
virtual void OnListItemActivatedOrdersReceived( wxListEvent& event ){ event.Skip(); }
public:
wxMenu* m_menuOptions;
wxListCtrl* m_listCtrl;
wxListCtrl* m_listCtrlEscrows;
wxListCtrl* m_listCtrlOrdersSent;
wxListCtrl* m_listCtrlProductsSent;
wxListCtrl* m_listCtrlOrdersReceived;
CMainFrameBase( wxWindow* parent, wxWindowID id = wxID_MAINFRAME, const wxString& title = wxT("Bitcoin"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 705,484 ), long style = wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER|wxTAB_TRAVERSAL );
wxTextCtrl* m_textCtrlAddress;
wxListCtrl* m_listCtrlAll;
wxListCtrl* m_listCtrlSentReceived;
wxListCtrl* m_listCtrlSent;
wxListCtrl* m_listCtrlReceived;
CMainFrameBase( wxWindow* parent, wxWindowID id = wxID_MAINFRAME, const wxString& title = _("Bitcoin"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 723,484 ), long style = wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER|wxTAB_TRAVERSAL );
~CMainFrameBase();
};
@@ -179,7 +148,7 @@ class CTxDetailsDialogBase : public wxDialog
public:
CTxDetailsDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Transaction Details"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 620,450 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
CTxDetailsDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Transaction Details"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 620,450 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~CTxDetailsDialogBase();
};
@@ -215,8 +184,6 @@ class COptionsDialogBase : public wxDialog
wxStaticText* m_staticText321;
wxStaticText* m_staticText69;
wxStaticText* m_staticText70;
wxStaticText* m_staticText71;
wxButton* m_buttonOK;
wxButton* m_buttonCancel;
wxButton* m_buttonApply;
@@ -234,7 +201,7 @@ class COptionsDialogBase : public wxDialog
public:
COptionsDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Options"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 540,360 ), long style = wxDEFAULT_DIALOG_STYLE );
COptionsDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Options"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 540,360 ), long style = wxDEFAULT_DIALOG_STYLE );
~COptionsDialogBase();
};
@@ -247,7 +214,7 @@ class CAboutDialogBase : public wxDialog
private:
protected:
wxStaticBitmap* m_bitmap;
wxStaticText* m_staticText40;
@@ -262,7 +229,7 @@ class CAboutDialogBase : public wxDialog
public:
wxStaticText* m_staticTextVersion;
CAboutDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("About Bitcoin"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 507,298 ), long style = wxDEFAULT_DIALOG_STYLE );
CAboutDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("About Bitcoin"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 532,329 ), long style = wxDEFAULT_DIALOG_STYLE );
~CAboutDialogBase();
};
@@ -309,7 +276,7 @@ class CSendDialogBase : public wxDialog
public:
CSendDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Send Coins"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 675,312 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
CSendDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Send Coins"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 675,312 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~CSendDialogBase();
};
@@ -336,7 +303,7 @@ class CSendingDialogBase : public wxDialog
public:
CSendingDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Sending..."), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 442,151 ), long style = wxDEFAULT_DIALOG_STYLE );
CSendingDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Sending..."), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 442,151 ), long style = wxDEFAULT_DIALOG_STYLE );
~CSendingDialogBase();
};
@@ -372,7 +339,7 @@ class CYourAddressDialogBase : public wxDialog
public:
CYourAddressDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Your Bitcoin Addresses"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 610,390 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
CYourAddressDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Your Bitcoin Addresses"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 610,390 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~CYourAddressDialogBase();
};
@@ -385,265 +352,44 @@ class CAddressBookDialogBase : public wxDialog
private:
protected:
wxNotebook* m_notebook;
wxPanel* m_panelSending;
wxStaticText* m_staticText55;
wxListCtrl* m_listCtrl;
wxListCtrl* m_listCtrlSending;
wxPanel* m_panelReceiving;
wxStaticText* m_staticText45;
wxListCtrl* m_listCtrlReceiving;
wxButton* m_buttonDelete;
wxButton* m_buttonCopy;
wxButton* m_buttonEdit;
wxButton* m_buttonNew;
wxButton* m_buttonDelete;
wxButton* m_buttonOK;
// Virtual event handlers, overide them in your derived class
virtual void OnClose( wxCloseEvent& event ){ event.Skip(); }
virtual void OnNotebookPageChanged( wxNotebookEvent& event ){ event.Skip(); }
virtual void OnListEndLabelEdit( wxListEvent& event ){ event.Skip(); }
virtual void OnListItemActivated( wxListEvent& event ){ event.Skip(); }
virtual void OnListItemSelected( wxListEvent& event ){ event.Skip(); }
virtual void OnButtonDelete( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonCopy( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonEdit( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonNew( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonDelete( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonOK( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonCancel( wxCommandEvent& event ){ event.Skip(); }
public:
wxButton* m_buttonCancel;
CAddressBookDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Address Book"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 610,390 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
CAddressBookDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Address Book"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 610,390 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~CAddressBookDialogBase();
};
///////////////////////////////////////////////////////////////////////////////
/// Class CProductsDialogBase
///////////////////////////////////////////////////////////////////////////////
class CProductsDialogBase : public wxDialog
{
private:
protected:
wxComboBox* m_comboBoxCategory;
wxTextCtrl* m_textCtrlSearch;
wxButton* m_buttonSearch;
wxListCtrl* m_listCtrl;
// Virtual event handlers, overide them in your derived class
virtual void OnCombobox( wxCommandEvent& event ){ event.Skip(); }
virtual void OnKeyDown( wxKeyEvent& event ){ event.Skip(); }
virtual void OnButtonSearch( wxCommandEvent& event ){ event.Skip(); }
virtual void OnListItemActivated( wxListEvent& event ){ event.Skip(); }
public:
CProductsDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Marketplace"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 708,535 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~CProductsDialogBase();
};
///////////////////////////////////////////////////////////////////////////////
/// Class CEditProductDialogBase
///////////////////////////////////////////////////////////////////////////////
class CEditProductDialogBase : public wxFrame
{
private:
protected:
wxScrolledWindow* m_scrolledWindow;
wxStaticText* m_staticText106;
wxComboBox* m_comboBoxCategory;
wxStaticText* m_staticText108;
wxTextCtrl* m_textCtrlTitle;
wxStaticText* m_staticText107;
wxTextCtrl* m_textCtrlPrice;
wxStaticText* m_staticText22;
wxTextCtrl* m_textCtrlDescription;
wxStaticText* m_staticText23;
wxTextCtrl* m_textCtrlInstructions;
wxStaticText* m_staticText24;
wxStaticText* m_staticText25;
wxTextCtrl* m_textCtrlLabel0;
wxTextCtrl* m_textCtrlField0;
wxButton* m_buttonDel0;
wxTextCtrl* m_textCtrlLabel1;
wxTextCtrl* m_textCtrlField1;
wxButton* m_buttonDel1;
wxTextCtrl* m_textCtrlLabel2;
wxTextCtrl* m_textCtrlField2;
wxButton* m_buttonDel2;
wxTextCtrl* m_textCtrlLabel3;
wxTextCtrl* m_textCtrlField3;
wxButton* m_buttonDel3;
wxTextCtrl* m_textCtrlLabel4;
wxTextCtrl* m_textCtrlField4;
wxButton* m_buttonDel4;
wxTextCtrl* m_textCtrlLabel5;
wxTextCtrl* m_textCtrlField5;
wxButton* m_buttonDel5;
wxTextCtrl* m_textCtrlLabel6;
wxTextCtrl* m_textCtrlField6;
wxButton* m_buttonDel6;
wxTextCtrl* m_textCtrlLabel7;
wxTextCtrl* m_textCtrlField7;
wxButton* m_buttonDel7;
wxTextCtrl* m_textCtrlLabel8;
wxTextCtrl* m_textCtrlField8;
wxButton* m_buttonDel8;
wxTextCtrl* m_textCtrlLabel9;
wxTextCtrl* m_textCtrlField9;
wxButton* m_buttonDel9;
wxTextCtrl* m_textCtrlLabel10;
wxTextCtrl* m_textCtrlField10;
wxButton* m_buttonDel10;
wxTextCtrl* m_textCtrlLabel11;
wxTextCtrl* m_textCtrlField11;
wxButton* m_buttonDel11;
wxTextCtrl* m_textCtrlLabel12;
wxTextCtrl* m_textCtrlField12;
wxButton* m_buttonDel12;
wxTextCtrl* m_textCtrlLabel13;
wxTextCtrl* m_textCtrlField13;
wxButton* m_buttonDel13;
wxTextCtrl* m_textCtrlLabel14;
wxTextCtrl* m_textCtrlField14;
wxButton* m_buttonDel14;
wxTextCtrl* m_textCtrlLabel15;
wxTextCtrl* m_textCtrlField15;
wxButton* m_buttonDel15;
wxTextCtrl* m_textCtrlLabel16;
wxTextCtrl* m_textCtrlField16;
wxButton* m_buttonDel16;
wxTextCtrl* m_textCtrlLabel17;
wxTextCtrl* m_textCtrlField17;
wxButton* m_buttonDel17;
wxTextCtrl* m_textCtrlLabel18;
wxTextCtrl* m_textCtrlField18;
wxButton* m_buttonDel18;
wxTextCtrl* m_textCtrlLabel19;
wxTextCtrl* m_textCtrlField19;
wxButton* m_buttonDel19;
wxButton* m_buttonAddField;
wxButton* m_buttonOK;
wxButton* m_buttonPreview;
wxButton* m_buttonCancel;
// Virtual event handlers, overide them in your derived class
virtual void OnKeyDown( wxKeyEvent& event ){ event.Skip(); }
virtual void OnButtonDel0( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonDel1( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonDel2( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonDel3( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonDel4( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonDel5( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonDel6( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonDel7( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonDel8( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonDel9( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonDel10( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonDel11( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonDel12( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonDel13( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonDel14( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonDel15( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonDel16( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonDel17( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonDel18( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonDel19( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonAddField( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonSend( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonPreview( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonCancel( wxCommandEvent& event ){ event.Skip(); }
public:
wxFlexGridSizer* fgSizer5;
CEditProductDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Edit Product"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 660,640 ), long style = wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER|wxTAB_TRAVERSAL );
~CEditProductDialogBase();
};
///////////////////////////////////////////////////////////////////////////////
/// Class CViewProductDialogBase
///////////////////////////////////////////////////////////////////////////////
class CViewProductDialogBase : public wxFrame
{
private:
protected:
wxHtmlWindow* m_htmlWinReviews;
wxScrolledWindow* m_scrolledWindow;
wxRichTextCtrl* m_richTextHeading;
wxStaticText* m_staticTextInstructions;
wxButton* m_buttonSubmitForm;
wxButton* m_buttonCancelForm;
wxButton* m_buttonBack;
wxButton* m_buttonNext;
wxButton* m_buttonCancel;
// Virtual event handlers, overide them in your derived class
virtual void OnButtonSubmitForm( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonCancelForm( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonBack( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonNext( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonCancel( wxCommandEvent& event ){ event.Skip(); }
public:
CViewProductDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Order Form"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 630,520 ), long style = wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER|wxTAB_TRAVERSAL );
~CViewProductDialogBase();
};
///////////////////////////////////////////////////////////////////////////////
/// Class CViewOrderDialogBase
///////////////////////////////////////////////////////////////////////////////
class CViewOrderDialogBase : public wxFrame
{
private:
protected:
wxHtmlWindow* m_htmlWin;
wxButton* m_buttonOK;
// Virtual event handlers, overide them in your derived class
virtual void OnButtonOK( wxCommandEvent& event ){ event.Skip(); }
public:
CViewOrderDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("View Order"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 630,520 ), long style = wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER|wxTAB_TRAVERSAL );
~CViewOrderDialogBase();
};
///////////////////////////////////////////////////////////////////////////////
/// Class CEditReviewDialogBase
///////////////////////////////////////////////////////////////////////////////
class CEditReviewDialogBase : public wxFrame
{
private:
protected:
wxStaticText* m_staticTextSeller;
wxStaticText* m_staticText110;
wxChoice* m_choiceStars;
wxStaticText* m_staticText43;
wxTextCtrl* m_textCtrlReview;
wxButton* m_buttonSubmit;
wxButton* m_buttonCancel;
// Virtual event handlers, overide them in your derived class
virtual void OnKeyDown( wxKeyEvent& event ){ event.Skip(); }
virtual void OnButtonSubmit( wxCommandEvent& event ){ event.Skip(); }
virtual void OnButtonCancel( wxCommandEvent& event ){ event.Skip(); }
public:
CEditReviewDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Enter Review"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 630,440 ), long style = wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER|wxTAB_TRAVERSAL );
~CEditReviewDialogBase();
};
///////////////////////////////////////////////////////////////////////////////
/// Class CGetTextFromUserDialogBase
///////////////////////////////////////////////////////////////////////////////
@@ -670,7 +416,7 @@ class CGetTextFromUserDialogBase : public wxDialog
public:
CGetTextFromUserDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 403,138 ), long style = wxDEFAULT_DIALOG_STYLE );
CGetTextFromUserDialogBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 440,138 ), long style = wxDEFAULT_DIALOG_STYLE );
~CGetTextFromUserDialogBase();
};

View File

@@ -299,19 +299,18 @@ public:
return string(psz, psz + sizeof(pn)*2);
}
void SetHex(const std::string& str)
void SetHex(const char* psz)
{
for (int i = 0; i < WIDTH; i++)
pn[i] = 0;
// skip 0x
const char* psz = str.c_str();
// skip leading spaces
while (isspace(*psz))
psz++;
// skip 0x
if (psz[0] == '0' && tolower(psz[1]) == 'x')
psz += 2;
while (isspace(*psz))
psz++;
// hex string to uint
static char phexdigit[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0xa,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0,0,0,0,0 };
@@ -332,6 +331,11 @@ public:
}
}
void SetHex(const std::string& str)
{
SetHex(str.c_str());
}
std::string ToString() const
{
return (GetHex());

File diff suppressed because it is too large Load Diff

121
util.cpp
View File

@@ -1,4 +1,4 @@
// Copyright (c) 2009 Satoshi Nakamoto
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
@@ -8,10 +8,12 @@
map<string, string> mapArgs;
map<string, vector<string> > mapMultiArgs;
bool fDebug = false;
bool fPrintToDebugger = false;
bool fPrintToConsole = false;
bool fPrintToDebugger = false;
char pszSetDataDir[MAX_PATH] = "";
bool fShutdown = false;
bool fDaemon = false;
bool fCommandLine = false;
@@ -75,6 +77,8 @@ void RandAddSeed()
void RandAddSeedPerfmon()
{
RandAddSeed();
// This can take up to 2 seconds, so only do it every 10 minutes
static int64 nLastPerfmon;
if (GetTime() < nLastPerfmon + 10 * 60)
@@ -87,7 +91,7 @@ void RandAddSeedPerfmon()
unsigned char pdata[250000];
memset(pdata, 0, sizeof(pdata));
unsigned long nSize = sizeof(pdata);
long ret = RegQueryValueEx(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize);
long ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize);
RegCloseKey(HKEY_PERFORMANCE_DATA);
if (ret == ERROR_SUCCESS)
{
@@ -129,6 +133,79 @@ uint64 GetRand(uint64 nMax)
inline int OutputDebugStringF(const char* pszFormat, ...)
{
int ret = 0;
if (fPrintToConsole || wxTheApp == NULL)
{
// print to console
va_list arg_ptr;
va_start(arg_ptr, pszFormat);
ret = vprintf(pszFormat, arg_ptr);
va_end(arg_ptr);
}
else
{
// print to debug.log
char pszFile[MAX_PATH+100];
GetDataDir(pszFile);
strlcat(pszFile, "/debug.log", sizeof(pszFile));
FILE* fileout = fopen(pszFile, "a");
if (fileout)
{
//// Debug print useful for profiling
//fprintf(fileout, " %"PRI64d" ", wxGetLocalTimeMillis().GetValue());
va_list arg_ptr;
va_start(arg_ptr, pszFormat);
ret = vfprintf(fileout, pszFormat, arg_ptr);
va_end(arg_ptr);
fclose(fileout);
}
}
#ifdef __WXMSW__
if (fPrintToDebugger)
{
// accumulate a line at a time
static CCriticalSection cs_OutputDebugStringF;
CRITICAL_BLOCK(cs_OutputDebugStringF)
{
static char pszBuffer[50000];
static char* pend;
if (pend == NULL)
pend = pszBuffer;
va_list arg_ptr;
va_start(arg_ptr, pszFormat);
int limit = END(pszBuffer) - pend - 2;
int ret = _vsnprintf(pend, limit, pszFormat, arg_ptr);
va_end(arg_ptr);
if (ret < 0 || ret >= limit)
{
pend = END(pszBuffer) - 2;
*pend++ = '\n';
}
else
pend += ret;
*pend = '\0';
char* p1 = pszBuffer;
char* p2;
while (p2 = strchr(p1, '\n'))
{
p2++;
char c = *p2;
*p2 = '\0';
OutputDebugStringA(p1);
*p2 = c;
p1 = p2;
}
if (p1 != pszBuffer)
memmove(pszBuffer, p1, pend - p1 + 1);
pend -= (p1 - pszBuffer);
}
}
#endif
return ret;
}
// Safer snprintf
@@ -355,6 +432,39 @@ void ParseParameters(int argc, char* argv[])
}
const char* wxGetTranslation(const char* pszEnglish)
{
// Wrapper of wxGetTranslation returning the same const char* type as was passed in
static CCriticalSection cs;
CRITICAL_BLOCK(cs)
{
// Look in cache
static map<string, char*> mapCache;
map<string, char*>::iterator mi = mapCache.find(pszEnglish);
if (mi != mapCache.end())
return (*mi).second;
// wxWidgets translation
const char* pszTranslated = wxGetTranslation(wxString(pszEnglish, wxConvUTF8)).utf8_str();
// We don't cache unknown strings because caller might be passing in a
// dynamic string and we would keep allocating memory for each variation.
if (strcmp(pszEnglish, pszTranslated) == 0)
return pszEnglish;
// Add to cache, memory doesn't need to be freed. We only cache because
// we must pass back a pointer to permanently allocated memory.
char* pszCached = new char[strlen(pszTranslated)+1];
strcpy(pszCached, pszTranslated);
mapCache[pszEnglish] = pszCached;
return pszCached;
}
}
@@ -365,7 +475,7 @@ void FormatException(char* pszMessage, std::exception* pex, const char* pszThrea
#ifdef __WXMSW__
char pszModule[MAX_PATH];
pszModule[0] = '\0';
GetModuleFileName(NULL, pszModule, sizeof(pszModule));
GetModuleFileNameA(NULL, pszModule, sizeof(pszModule));
#else
// might not be thread safe, uses wxString
//const char* pszModule = wxStandardPaths::Get().GetExecutablePath().mb_str();
@@ -391,7 +501,8 @@ void PrintException(std::exception* pex, const char* pszThread)
char pszMessage[1000];
FormatException(pszMessage, pex, pszThread);
printf("\n\n************************\n%s\n", pszMessage);
if (wxTheApp)
fprintf(stderr, "\n\n************************\n%s\n", pszMessage);
if (wxTheApp && !fDaemon)
wxMessageBox(pszMessage, "Error", wxOK | wxICON_ERROR);
throw;
//DebugBreak();

119
util.h
View File

@@ -1,4 +1,4 @@
// Copyright (c) 2009 Satoshi Nakamoto
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
@@ -55,6 +55,7 @@ inline T& REF(const T& val)
}
#ifdef __WXMSW__
static const bool fWindows = true;
#define MSG_NOSIGNAL 0
#define MSG_DONTWAIT 0
#ifndef UINT64_MAX
@@ -66,7 +67,10 @@ inline T& REF(const T& val)
#define S_IRUSR 0400
#define S_IWUSR 0200
#endif
#define unlink _unlink
typedef int socklen_t;
#else
static const bool fWindows = false;
#define WSAGetLastError() errno
#define WSAEWOULDBLOCK EWOULDBLOCK
#define WSAEMSGSIZE EMSGSIZE
@@ -112,13 +116,16 @@ inline int myclosesocket(SOCKET& hSocket)
extern map<string, string> mapArgs;
extern map<string, vector<string> > mapMultiArgs;
extern bool fDebug;
extern bool fPrintToDebugger;
extern bool fPrintToConsole;
extern bool fPrintToDebugger;
extern char pszSetDataDir[MAX_PATH];
extern bool fShutdown;
extern bool fDaemon;
extern bool fCommandLine;
void RandAddSeed();
void RandAddSeedPerfmon();
int OutputDebugStringF(const char* pszFormat, ...);
int my_snprintf(char* buffer, size_t limit, const char* format, ...);
string strprintf(const char* format, ...);
bool error(const char* format, ...);
@@ -130,6 +137,7 @@ bool ParseMoney(const char* pszIn, int64& nRet);
vector<unsigned char> ParseHex(const char* psz);
vector<unsigned char> ParseHex(const std::string& str);
void ParseParameters(int argc, char* argv[]);
const char* wxGetTranslation(const char* psz);
int GetFilesize(FILE* file);
void GetDataDir(char* pszDirRet);
string GetDataDir();
@@ -219,92 +227,6 @@ public:
inline int OutputDebugStringF(const char* pszFormat, ...)
{
int ret = 0;
#ifdef __WXDEBUG__
if (!fPrintToConsole)
{
// print to debug.log
char pszFile[MAX_PATH+100];
GetDataDir(pszFile);
strlcat(pszFile, "/debug.log", sizeof(pszFile));
FILE* fileout = fopen(pszFile, "a");
if (fileout)
{
//// Debug print useful for profiling
//fprintf(fileout, " %"PRI64d" ", wxGetLocalTimeMillis().GetValue());
va_list arg_ptr;
va_start(arg_ptr, pszFormat);
ret = vfprintf(fileout, pszFormat, arg_ptr);
va_end(arg_ptr);
fclose(fileout);
}
}
#ifdef __WXMSW__
if (fPrintToDebugger)
{
// accumulate a line at a time
static CCriticalSection cs_OutputDebugStringF;
CRITICAL_BLOCK(cs_OutputDebugStringF)
{
static char pszBuffer[50000];
static char* pend;
if (pend == NULL)
pend = pszBuffer;
va_list arg_ptr;
va_start(arg_ptr, pszFormat);
int limit = END(pszBuffer) - pend - 2;
int ret = _vsnprintf(pend, limit, pszFormat, arg_ptr);
va_end(arg_ptr);
if (ret < 0 || ret >= limit)
{
pend = END(pszBuffer) - 2;
*pend++ = '\n';
}
else
pend += ret;
*pend = '\0';
char* p1 = pszBuffer;
char* p2;
while (p2 = strchr(p1, '\n'))
{
p2++;
char c = *p2;
*p2 = '\0';
OutputDebugString(p1);
*p2 = c;
p1 = p2;
}
if (p1 != pszBuffer)
memmove(pszBuffer, p1, pend - p1 + 1);
pend -= (p1 - pszBuffer);
}
}
#endif
#endif
if (fPrintToConsole)
{
// print to console
va_list arg_ptr;
va_start(arg_ptr, pszFormat);
ret = vprintf(pszFormat, arg_ptr);
va_end(arg_ptr);
}
return ret;
}
inline string i64tostr(int64 n)
{
return strprintf("%"PRI64d, n);
@@ -343,6 +265,11 @@ inline int roundint(double d)
return (int)(d > 0 ? d + 0.5 : d - 0.5);
}
inline int64 roundint64(double d)
{
return (int64)(d > 0 ? d + 0.5 : d - 0.5);
}
template<typename T>
string HexStr(const T itbegin, const T itend, bool fSpaces=true)
{
@@ -408,6 +335,17 @@ inline string DateTimeStrFormat(const char* pszFormat, int64 nTime)
return pszTime;
}
template<typename T>
void skipspaces(T& it)
{
while (isspace(*it))
++it;
}
@@ -418,8 +356,9 @@ inline string DateTimeStrFormat(const char* pszFormat, int64 nTime)
inline void heapchk()
{
#ifdef __WXMSW__
if (_heapchk() != _HEAPOK)
DebugBreak();
/// for debugging
//if (_heapchk() != _HEAPOK)
// DebugBreak();
#endif
}

665
xpm/about.xpm Normal file
View File

@@ -0,0 +1,665 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
/* XPM */
static const char * about_xpm[] = {
/* columns rows colors chars-per-pixel */
"96 564 92 1",
" c #001269",
". c #000C72",
"X c #00057F",
"o c #001175",
"O c #000B6A",
"+ c #000E84",
"@ c #000489",
"# c #001583",
"$ c #001B89",
"% c #001B99",
"& c #000B92",
"* c #00208B",
"= c #002B97",
"- c #0004A6",
"; c #001DA7",
": c #0014BC",
"> c #0019BB",
", c #0017B4",
"< c #0023A3",
"1 c #002CAA",
"2 c #0030A4",
"3 c #003BA3",
"4 c #0033AB",
"5 c #003FA8",
"6 c #0027B8",
"7 c #0035BB",
"8 c #003CBA",
"9 c #004ABD",
"0 c #001DC4",
"q c #0017CC",
"w c #000CD0",
"e c #0026C7",
"r c #0035C4",
"t c #003DC5",
"y c #0032CB",
"u c #003BCC",
"i c #002BD3",
"p c #0021DC",
"a c #0025D5",
"s c #0034D5",
"d c #003ADB",
"f c #0016F6",
"g c #0008F9",
"h c #0027E3",
"j c #003CE9",
"k c #002BF5",
"l c #0024F9",
"z c #0033F4",
"x c #0035F8",
"c c #0048CA",
"v c #0055C5",
"b c #0059C3",
"n c #0053CB",
"m c #005ACC",
"M c #004FD4",
"N c #004CDC",
"B c #0047D0",
"V c #005BD6",
"C c #0049E5",
"Z c #0042EA",
"A c #0052E4",
"S c #005CE4",
"D c #0054EC",
"F c #005EEB",
"G c #004AF5",
"H c #0051F2",
"J c #005CFA",
"K c #0058F9",
"L c #0066E4",
"P c #006BE3",
"I c #0064EC",
"U c #006DEF",
"Y c #0074EB",
"T c #0078EC",
"R c #0073E7",
"E c #0065F4",
"W c #006BF5",
"Q c #006BFB",
"! c #0066FD",
"~ c #0073F5",
"^ c #007CF3",
"/ c #0075FB",
"( c #007DFC",
") c #0084FF",
"_ c #008AFF",
"` c #0092FF",
"' c #339CFF",
"] c #33A3FF",
"[ c #33AAFF",
"{ c #66B5FF",
"} c #66BBFF",
"| c #66C0FF",
/* pixels */
"kkkkkkkkkkkk<<<<<<<<<<<<DDDDDDDDDDDDvvvvvvvvvvvv////////////))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"kkkkkkkkkkkk<<<<<<<<<<<<DDDDDDDDDDDDvvvvvvvvvvvv////////////))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"kkkkkkkkkkkk<<<<<<<<<<<<DDDDDDDDDDDDvvvvvvvvvvvv////////////))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"kkkkkkkkkkkk<<<<<<<<<<<<DDDDDDDDDDDDvvvvvvvvvvvv////////////))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"kkkkkkkkkkkk<<<<<<<<<<<<DDDDDDDDDDDDvvvvvvvvvvvv////////////))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"kkkkkkkkkkkk<<<<<<<<<<<<DDDDDDDDDDDDvvvvvvvvvvvv////////////))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"kkkkkkkkkkkk<<<<<<<<<<<<DDDDDDDDDDDDvvvvvvvvvvvv////////////))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"kkkkkkkkkkkk<<<<<<<<<<<<DDDDDDDDDDDDvvvvvvvvvvvv////////////))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"kkkkkkkkkkkk<<<<<<<<<<<<DDDDDDDDDDDDvvvvvvvvvvvv////////////))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"kkkkkkkkkkkk<<<<<<<<<<<<DDDDDDDDDDDDvvvvvvvvvvvv////////////))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"kkkkkkkkkkkk<<<<<<<<<<<<DDDDDDDDDDDDvvvvvvvvvvvv////////////))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"kkkkkkkkkkkk<<<<<<<<<<<<DDDDDDDDDDDDvvvvvvvvvvvv////////////))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"XXXXXXXXXXXXrrrrrrrrrrrr777777777777MMMMMMMMMMMM(((((((((((())))))))))))[[[[[[[[[[[[}}}}}}}}}}}}",
"XXXXXXXXXXXXrrrrrrrrrrrr777777777777MMMMMMMMMMMM(((((((((((())))))))))))[[[[[[[[[[[[}}}}}}}}}}}}",
"XXXXXXXXXXXXrrrrrrrrrrrr777777777777MMMMMMMMMMMM(((((((((((())))))))))))[[[[[[[[[[[[}}}}}}}}}}}}",
"XXXXXXXXXXXXrrrrrrrrrrrr777777777777MMMMMMMMMMMM(((((((((((())))))))))))[[[[[[[[[[[[}}}}}}}}}}}}",
"XXXXXXXXXXXXrrrrrrrrrrrr777777777777MMMMMMMMMMMM(((((((((((())))))))))))[[[[[[[[[[[[}}}}}}}}}}}}",
"XXXXXXXXXXXXrrrrrrrrrrrr777777777777MMMMMMMMMMMM(((((((((((())))))))))))[[[[[[[[[[[[}}}}}}}}}}}}",
"XXXXXXXXXXXXrrrrrrrrrrrr777777777777MMMMMMMMMMMM(((((((((((())))))))))))[[[[[[[[[[[[}}}}}}}}}}}}",
"XXXXXXXXXXXXrrrrrrrrrrrr777777777777MMMMMMMMMMMM(((((((((((())))))))))))[[[[[[[[[[[[}}}}}}}}}}}}",
"XXXXXXXXXXXXrrrrrrrrrrrr777777777777MMMMMMMMMMMM(((((((((((())))))))))))[[[[[[[[[[[[}}}}}}}}}}}}",
"XXXXXXXXXXXXrrrrrrrrrrrr777777777777MMMMMMMMMMMM(((((((((((())))))))))))[[[[[[[[[[[[}}}}}}}}}}}}",
"XXXXXXXXXXXXrrrrrrrrrrrr777777777777MMMMMMMMMMMM(((((((((((())))))))))))[[[[[[[[[[[[}}}}}}}}}}}}",
"XXXXXXXXXXXXrrrrrrrrrrrr777777777777MMMMMMMMMMMM(((((((((((())))))))))))[[[[[[[[[[[[}}}}}}}}}}}}",
"llllllllllll;;;;;;;;;;;;NNNNNNNNNNNNSSSSSSSSSSSS~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"llllllllllll;;;;;;;;;;;;NNNNNNNNNNNNSSSSSSSSSSSS~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"llllllllllll;;;;;;;;;;;;NNNNNNNNNNNNSSSSSSSSSSSS~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"llllllllllll;;;;;;;;;;;;NNNNNNNNNNNNSSSSSSSSSSSS~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"llllllllllll;;;;;;;;;;;;NNNNNNNNNNNNSSSSSSSSSSSS~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"llllllllllll;;;;;;;;;;;;NNNNNNNNNNNNSSSSSSSSSSSS~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"llllllllllll;;;;;;;;;;;;NNNNNNNNNNNNSSSSSSSSSSSS~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"llllllllllll;;;;;;;;;;;;NNNNNNNNNNNNSSSSSSSSSSSS~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"llllllllllll;;;;;;;;;;;;NNNNNNNNNNNNSSSSSSSSSSSS~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"llllllllllll;;;;;;;;;;;;NNNNNNNNNNNNSSSSSSSSSSSS~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"llllllllllll;;;;;;;;;;;;NNNNNNNNNNNNSSSSSSSSSSSS~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"llllllllllll;;;;;;;;;;;;NNNNNNNNNNNNSSSSSSSSSSSS~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"############666666666666uuuuuuuuuuuuJJJJJJJJJJJJ^^^^^^^^^^^^____________]]]]]]]]]]]]{{{{{{{{{{{{",
"############666666666666uuuuuuuuuuuuJJJJJJJJJJJJ^^^^^^^^^^^^____________]]]]]]]]]]]]{{{{{{{{{{{{",
"############666666666666uuuuuuuuuuuuJJJJJJJJJJJJ^^^^^^^^^^^^____________]]]]]]]]]]]]{{{{{{{{{{{{",
"############666666666666uuuuuuuuuuuuJJJJJJJJJJJJ^^^^^^^^^^^^____________]]]]]]]]]]]]{{{{{{{{{{{{",
"############666666666666uuuuuuuuuuuuJJJJJJJJJJJJ^^^^^^^^^^^^____________]]]]]]]]]]]]{{{{{{{{{{{{",
"############666666666666uuuuuuuuuuuuJJJJJJJJJJJJ^^^^^^^^^^^^____________]]]]]]]]]]]]{{{{{{{{{{{{",
"############666666666666uuuuuuuuuuuuJJJJJJJJJJJJ^^^^^^^^^^^^____________]]]]]]]]]]]]{{{{{{{{{{{{",
"############666666666666uuuuuuuuuuuuJJJJJJJJJJJJ^^^^^^^^^^^^____________]]]]]]]]]]]]{{{{{{{{{{{{",
"############666666666666uuuuuuuuuuuuJJJJJJJJJJJJ^^^^^^^^^^^^____________]]]]]]]]]]]]{{{{{{{{{{{{",
"############666666666666uuuuuuuuuuuuJJJJJJJJJJJJ^^^^^^^^^^^^____________]]]]]]]]]]]]{{{{{{{{{{{{",
"############666666666666uuuuuuuuuuuuJJJJJJJJJJJJ^^^^^^^^^^^^____________]]]]]]]]]]]]{{{{{{{{{{{{",
"############666666666666uuuuuuuuuuuuJJJJJJJJJJJJ^^^^^^^^^^^^____________]]]]]]]]]]]]{{{{{{{{{{{{",
"............yyyyyyyyyyyy333333333333AAAAAAAAAAAAWWWWWWWWWWWW____________[[[[[[[[[[[[{{{{{{{{{{{{",
"............yyyyyyyyyyyy333333333333AAAAAAAAAAAAWWWWWWWWWWWW____________[[[[[[[[[[[[{{{{{{{{{{{{",
"............yyyyyyyyyyyy333333333333AAAAAAAAAAAAWWWWWWWWWWWW____________[[[[[[[[[[[[{{{{{{{{{{{{",
"............yyyyyyyyyyyy333333333333AAAAAAAAAAAAWWWWWWWWWWWW____________[[[[[[[[[[[[{{{{{{{{{{{{",
"............yyyyyyyyyyyy333333333333AAAAAAAAAAAAWWWWWWWWWWWW____________[[[[[[[[[[[[{{{{{{{{{{{{",
"............yyyyyyyyyyyy333333333333AAAAAAAAAAAAWWWWWWWWWWWW____________[[[[[[[[[[[[{{{{{{{{{{{{",
"............yyyyyyyyyyyy333333333333AAAAAAAAAAAAWWWWWWWWWWWW____________[[[[[[[[[[[[{{{{{{{{{{{{",
"............yyyyyyyyyyyy333333333333AAAAAAAAAAAAWWWWWWWWWWWW____________[[[[[[[[[[[[{{{{{{{{{{{{",
"............yyyyyyyyyyyy333333333333AAAAAAAAAAAAWWWWWWWWWWWW____________[[[[[[[[[[[[{{{{{{{{{{{{",
"............yyyyyyyyyyyy333333333333AAAAAAAAAAAAWWWWWWWWWWWW____________[[[[[[[[[[[[{{{{{{{{{{{{",
"............yyyyyyyyyyyy333333333333AAAAAAAAAAAAWWWWWWWWWWWW____________[[[[[[[[[[[[{{{{{{{{{{{{",
"............yyyyyyyyyyyy333333333333AAAAAAAAAAAAWWWWWWWWWWWW____________[[[[[[[[[[[[{{{{{{{{{{{{",
"ffffffffffff============yyyyyyyyyyyyJJJJJJJJJJJJRRRRRRRRRRRR))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ffffffffffff============yyyyyyyyyyyyJJJJJJJJJJJJRRRRRRRRRRRR))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ffffffffffff============yyyyyyyyyyyyJJJJJJJJJJJJRRRRRRRRRRRR))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ffffffffffff============yyyyyyyyyyyyJJJJJJJJJJJJRRRRRRRRRRRR))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ffffffffffff============yyyyyyyyyyyyJJJJJJJJJJJJRRRRRRRRRRRR))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ffffffffffff============yyyyyyyyyyyyJJJJJJJJJJJJRRRRRRRRRRRR))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ffffffffffff============yyyyyyyyyyyyJJJJJJJJJJJJRRRRRRRRRRRR))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ffffffffffff============yyyyyyyyyyyyJJJJJJJJJJJJRRRRRRRRRRRR))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ffffffffffff============yyyyyyyyyyyyJJJJJJJJJJJJRRRRRRRRRRRR))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ffffffffffff============yyyyyyyyyyyyJJJJJJJJJJJJRRRRRRRRRRRR))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ffffffffffff============yyyyyyyyyyyyJJJJJJJJJJJJRRRRRRRRRRRR))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ffffffffffff============yyyyyyyyyyyyJJJJJJJJJJJJRRRRRRRRRRRR))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"gggggggggggg$$$$$$$$$$$$uuuuuuuuuuuuNNNNNNNNNNNN~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"gggggggggggg$$$$$$$$$$$$uuuuuuuuuuuuNNNNNNNNNNNN~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"gggggggggggg$$$$$$$$$$$$uuuuuuuuuuuuNNNNNNNNNNNN~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"gggggggggggg$$$$$$$$$$$$uuuuuuuuuuuuNNNNNNNNNNNN~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"gggggggggggg$$$$$$$$$$$$uuuuuuuuuuuuNNNNNNNNNNNN~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"gggggggggggg$$$$$$$$$$$$uuuuuuuuuuuuNNNNNNNNNNNN~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"gggggggggggg$$$$$$$$$$$$uuuuuuuuuuuuNNNNNNNNNNNN~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"gggggggggggg$$$$$$$$$$$$uuuuuuuuuuuuNNNNNNNNNNNN~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"gggggggggggg$$$$$$$$$$$$uuuuuuuuuuuuNNNNNNNNNNNN~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"gggggggggggg$$$$$$$$$$$$uuuuuuuuuuuuNNNNNNNNNNNN~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"gggggggggggg$$$$$$$$$$$$uuuuuuuuuuuuNNNNNNNNNNNN~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"gggggggggggg$$$$$$$$$$$$uuuuuuuuuuuuNNNNNNNNNNNN~~~~~~~~~~~~))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"::::::::::::hhhhhhhhhhhhddddddddddddAAAAAAAAAAAAUUUUUUUUUUUU))))))))))))''''''''''''}}}}}}}}}}}}",
"::::::::::::hhhhhhhhhhhhddddddddddddAAAAAAAAAAAAUUUUUUUUUUUU))))))))))))''''''''''''}}}}}}}}}}}}",
"::::::::::::hhhhhhhhhhhhddddddddddddAAAAAAAAAAAAUUUUUUUUUUUU))))))))))))''''''''''''}}}}}}}}}}}}",
"::::::::::::hhhhhhhhhhhhddddddddddddAAAAAAAAAAAAUUUUUUUUUUUU))))))))))))''''''''''''}}}}}}}}}}}}",
"::::::::::::hhhhhhhhhhhhddddddddddddAAAAAAAAAAAAUUUUUUUUUUUU))))))))))))''''''''''''}}}}}}}}}}}}",
"::::::::::::hhhhhhhhhhhhddddddddddddAAAAAAAAAAAAUUUUUUUUUUUU))))))))))))''''''''''''}}}}}}}}}}}}",
"::::::::::::hhhhhhhhhhhhddddddddddddAAAAAAAAAAAAUUUUUUUUUUUU))))))))))))''''''''''''}}}}}}}}}}}}",
"::::::::::::hhhhhhhhhhhhddddddddddddAAAAAAAAAAAAUUUUUUUUUUUU))))))))))))''''''''''''}}}}}}}}}}}}",
"::::::::::::hhhhhhhhhhhhddddddddddddAAAAAAAAAAAAUUUUUUUUUUUU))))))))))))''''''''''''}}}}}}}}}}}}",
"::::::::::::hhhhhhhhhhhhddddddddddddAAAAAAAAAAAAUUUUUUUUUUUU))))))))))))''''''''''''}}}}}}}}}}}}",
"::::::::::::hhhhhhhhhhhhddddddddddddAAAAAAAAAAAAUUUUUUUUUUUU))))))))))))''''''''''''}}}}}}}}}}}}",
"::::::::::::hhhhhhhhhhhhddddddddddddAAAAAAAAAAAAUUUUUUUUUUUU))))))))))))''''''''''''}}}}}}}}}}}}",
"zzzzzzzzzzzzGGGGGGGGGGGGBBBBBBBBBBBBDDDDDDDDDDDDPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"zzzzzzzzzzzzGGGGGGGGGGGGBBBBBBBBBBBBDDDDDDDDDDDDPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"zzzzzzzzzzzzGGGGGGGGGGGGBBBBBBBBBBBBDDDDDDDDDDDDPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"zzzzzzzzzzzzGGGGGGGGGGGGBBBBBBBBBBBBDDDDDDDDDDDDPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"zzzzzzzzzzzzGGGGGGGGGGGGBBBBBBBBBBBBDDDDDDDDDDDDPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"zzzzzzzzzzzzGGGGGGGGGGGGBBBBBBBBBBBBDDDDDDDDDDDDPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"zzzzzzzzzzzzGGGGGGGGGGGGBBBBBBBBBBBBDDDDDDDDDDDDPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"zzzzzzzzzzzzGGGGGGGGGGGGBBBBBBBBBBBBDDDDDDDDDDDDPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"zzzzzzzzzzzzGGGGGGGGGGGGBBBBBBBBBBBBDDDDDDDDDDDDPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"zzzzzzzzzzzzGGGGGGGGGGGGBBBBBBBBBBBBDDDDDDDDDDDDPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"zzzzzzzzzzzzGGGGGGGGGGGGBBBBBBBBBBBBDDDDDDDDDDDDPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"zzzzzzzzzzzzGGGGGGGGGGGGBBBBBBBBBBBBDDDDDDDDDDDDPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"ffffffffffffssssssssssssjjjjjjjjjjjjnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
"ffffffffffffssssssssssssjjjjjjjjjjjjnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
"ffffffffffffssssssssssssjjjjjjjjjjjjnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
"ffffffffffffssssssssssssjjjjjjjjjjjjnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
"ffffffffffffssssssssssssjjjjjjjjjjjjnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
"ffffffffffffssssssssssssjjjjjjjjjjjjnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
"ffffffffffffssssssssssssjjjjjjjjjjjjnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
"ffffffffffffssssssssssssjjjjjjjjjjjjnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
"ffffffffffffssssssssssssjjjjjjjjjjjjnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
"ffffffffffffssssssssssssjjjjjjjjjjjjnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
"ffffffffffffssssssssssssjjjjjjjjjjjjnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
"ffffffffffffssssssssssssjjjjjjjjjjjjnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
"wwwwwwwwwwww<<<<<<<<<<<<888888888888VVVVVVVVVVVV~~~~~~~~~~~~((((((((((((]]]]]]]]]]]]}}}}}}}}}}}}",
"wwwwwwwwwwww<<<<<<<<<<<<888888888888VVVVVVVVVVVV~~~~~~~~~~~~((((((((((((]]]]]]]]]]]]}}}}}}}}}}}}",
"wwwwwwwwwwww<<<<<<<<<<<<888888888888VVVVVVVVVVVV~~~~~~~~~~~~((((((((((((]]]]]]]]]]]]}}}}}}}}}}}}",
"wwwwwwwwwwww<<<<<<<<<<<<888888888888VVVVVVVVVVVV~~~~~~~~~~~~((((((((((((]]]]]]]]]]]]}}}}}}}}}}}}",
"wwwwwwwwwwww<<<<<<<<<<<<888888888888VVVVVVVVVVVV~~~~~~~~~~~~((((((((((((]]]]]]]]]]]]}}}}}}}}}}}}",
"wwwwwwwwwwww<<<<<<<<<<<<888888888888VVVVVVVVVVVV~~~~~~~~~~~~((((((((((((]]]]]]]]]]]]}}}}}}}}}}}}",
"wwwwwwwwwwww<<<<<<<<<<<<888888888888VVVVVVVVVVVV~~~~~~~~~~~~((((((((((((]]]]]]]]]]]]}}}}}}}}}}}}",
"wwwwwwwwwwww<<<<<<<<<<<<888888888888VVVVVVVVVVVV~~~~~~~~~~~~((((((((((((]]]]]]]]]]]]}}}}}}}}}}}}",
"wwwwwwwwwwww<<<<<<<<<<<<888888888888VVVVVVVVVVVV~~~~~~~~~~~~((((((((((((]]]]]]]]]]]]}}}}}}}}}}}}",
"wwwwwwwwwwww<<<<<<<<<<<<888888888888VVVVVVVVVVVV~~~~~~~~~~~~((((((((((((]]]]]]]]]]]]}}}}}}}}}}}}",
"wwwwwwwwwwww<<<<<<<<<<<<888888888888VVVVVVVVVVVV~~~~~~~~~~~~((((((((((((]]]]]]]]]]]]}}}}}}}}}}}}",
"wwwwwwwwwwww<<<<<<<<<<<<888888888888VVVVVVVVVVVV~~~~~~~~~~~~((((((((((((]]]]]]]]]]]]}}}}}}}}}}}}",
"hhhhhhhhhhhh>>>>>>>>>>>>rrrrrrrrrrrrVVVVVVVVVVVVLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"hhhhhhhhhhhh>>>>>>>>>>>>rrrrrrrrrrrrVVVVVVVVVVVVLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"hhhhhhhhhhhh>>>>>>>>>>>>rrrrrrrrrrrrVVVVVVVVVVVVLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"hhhhhhhhhhhh>>>>>>>>>>>>rrrrrrrrrrrrVVVVVVVVVVVVLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"hhhhhhhhhhhh>>>>>>>>>>>>rrrrrrrrrrrrVVVVVVVVVVVVLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"hhhhhhhhhhhh>>>>>>>>>>>>rrrrrrrrrrrrVVVVVVVVVVVVLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"hhhhhhhhhhhh>>>>>>>>>>>>rrrrrrrrrrrrVVVVVVVVVVVVLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"hhhhhhhhhhhh>>>>>>>>>>>>rrrrrrrrrrrrVVVVVVVVVVVVLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"hhhhhhhhhhhh>>>>>>>>>>>>rrrrrrrrrrrrVVVVVVVVVVVVLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"hhhhhhhhhhhh>>>>>>>>>>>>rrrrrrrrrrrrVVVVVVVVVVVVLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"hhhhhhhhhhhh>>>>>>>>>>>>rrrrrrrrrrrrVVVVVVVVVVVVLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"hhhhhhhhhhhh>>>>>>>>>>>>rrrrrrrrrrrrVVVVVVVVVVVVLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"::::::::::::;;;;;;;;;;;;HHHHHHHHHHHHccccccccccccQQQQQQQQQQQQ))))))))))))''''''''''''}}}}}}}}}}}}",
"::::::::::::;;;;;;;;;;;;HHHHHHHHHHHHccccccccccccQQQQQQQQQQQQ))))))))))))''''''''''''}}}}}}}}}}}}",
"::::::::::::;;;;;;;;;;;;HHHHHHHHHHHHccccccccccccQQQQQQQQQQQQ))))))))))))''''''''''''}}}}}}}}}}}}",
"::::::::::::;;;;;;;;;;;;HHHHHHHHHHHHccccccccccccQQQQQQQQQQQQ))))))))))))''''''''''''}}}}}}}}}}}}",
"::::::::::::;;;;;;;;;;;;HHHHHHHHHHHHccccccccccccQQQQQQQQQQQQ))))))))))))''''''''''''}}}}}}}}}}}}",
"::::::::::::;;;;;;;;;;;;HHHHHHHHHHHHccccccccccccQQQQQQQQQQQQ))))))))))))''''''''''''}}}}}}}}}}}}",
"::::::::::::;;;;;;;;;;;;HHHHHHHHHHHHccccccccccccQQQQQQQQQQQQ))))))))))))''''''''''''}}}}}}}}}}}}",
"::::::::::::;;;;;;;;;;;;HHHHHHHHHHHHccccccccccccQQQQQQQQQQQQ))))))))))))''''''''''''}}}}}}}}}}}}",
"::::::::::::;;;;;;;;;;;;HHHHHHHHHHHHccccccccccccQQQQQQQQQQQQ))))))))))))''''''''''''}}}}}}}}}}}}",
"::::::::::::;;;;;;;;;;;;HHHHHHHHHHHHccccccccccccQQQQQQQQQQQQ))))))))))))''''''''''''}}}}}}}}}}}}",
"::::::::::::;;;;;;;;;;;;HHHHHHHHHHHHccccccccccccQQQQQQQQQQQQ))))))))))))''''''''''''}}}}}}}}}}}}",
"::::::::::::;;;;;;;;;;;;HHHHHHHHHHHHccccccccccccQQQQQQQQQQQQ))))))))))))''''''''''''}}}}}}}}}}}}",
"qqqqqqqqqqqqkkkkkkkkkkkk333333333333AAAAAAAAAAAARRRRRRRRRRRR))))))))))))''''''''''''{{{{{{{{{{{{",
"qqqqqqqqqqqqkkkkkkkkkkkk333333333333AAAAAAAAAAAARRRRRRRRRRRR))))))))))))''''''''''''{{{{{{{{{{{{",
"qqqqqqqqqqqqkkkkkkkkkkkk333333333333AAAAAAAAAAAARRRRRRRRRRRR))))))))))))''''''''''''{{{{{{{{{{{{",
"qqqqqqqqqqqqkkkkkkkkkkkk333333333333AAAAAAAAAAAARRRRRRRRRRRR))))))))))))''''''''''''{{{{{{{{{{{{",
"qqqqqqqqqqqqkkkkkkkkkkkk333333333333AAAAAAAAAAAARRRRRRRRRRRR))))))))))))''''''''''''{{{{{{{{{{{{",
"qqqqqqqqqqqqkkkkkkkkkkkk333333333333AAAAAAAAAAAARRRRRRRRRRRR))))))))))))''''''''''''{{{{{{{{{{{{",
"qqqqqqqqqqqqkkkkkkkkkkkk333333333333AAAAAAAAAAAARRRRRRRRRRRR))))))))))))''''''''''''{{{{{{{{{{{{",
"qqqqqqqqqqqqkkkkkkkkkkkk333333333333AAAAAAAAAAAARRRRRRRRRRRR))))))))))))''''''''''''{{{{{{{{{{{{",
"qqqqqqqqqqqqkkkkkkkkkkkk333333333333AAAAAAAAAAAARRRRRRRRRRRR))))))))))))''''''''''''{{{{{{{{{{{{",
"qqqqqqqqqqqqkkkkkkkkkkkk333333333333AAAAAAAAAAAARRRRRRRRRRRR))))))))))))''''''''''''{{{{{{{{{{{{",
"qqqqqqqqqqqqkkkkkkkkkkkk333333333333AAAAAAAAAAAARRRRRRRRRRRR))))))))))))''''''''''''{{{{{{{{{{{{",
"qqqqqqqqqqqqkkkkkkkkkkkk333333333333AAAAAAAAAAAARRRRRRRRRRRR))))))))))))''''''''''''{{{{{{{{{{{{",
"############ppppppppppppssssssssssssIIIIIIIIIIII^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"############ppppppppppppssssssssssssIIIIIIIIIIII^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"############ppppppppppppssssssssssssIIIIIIIIIIII^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"############ppppppppppppssssssssssssIIIIIIIIIIII^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"############ppppppppppppssssssssssssIIIIIIIIIIII^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"############ppppppppppppssssssssssssIIIIIIIIIIII^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"############ppppppppppppssssssssssssIIIIIIIIIIII^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"############ppppppppppppssssssssssssIIIIIIIIIIII^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"############ppppppppppppssssssssssssIIIIIIIIIIII^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"############ppppppppppppssssssssssssIIIIIIIIIIII^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"############ppppppppppppssssssssssssIIIIIIIIIIII^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"############ppppppppppppssssssssssssIIIIIIIIIIII^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"++++++++++++rrrrrrrrrrrr777777777777MMMMMMMMMMMMIIIIIIIIIIII````````````''''''''''''{{{{{{{{{{{{",
"++++++++++++rrrrrrrrrrrr777777777777MMMMMMMMMMMMIIIIIIIIIIII````````````''''''''''''{{{{{{{{{{{{",
"++++++++++++rrrrrrrrrrrr777777777777MMMMMMMMMMMMIIIIIIIIIIII````````````''''''''''''{{{{{{{{{{{{",
"++++++++++++rrrrrrrrrrrr777777777777MMMMMMMMMMMMIIIIIIIIIIII````````````''''''''''''{{{{{{{{{{{{",
"++++++++++++rrrrrrrrrrrr777777777777MMMMMMMMMMMMIIIIIIIIIIII````````````''''''''''''{{{{{{{{{{{{",
"++++++++++++rrrrrrrrrrrr777777777777MMMMMMMMMMMMIIIIIIIIIIII````````````''''''''''''{{{{{{{{{{{{",
"++++++++++++rrrrrrrrrrrr777777777777MMMMMMMMMMMMIIIIIIIIIIII````````````''''''''''''{{{{{{{{{{{{",
"++++++++++++rrrrrrrrrrrr777777777777MMMMMMMMMMMMIIIIIIIIIIII````````````''''''''''''{{{{{{{{{{{{",
"++++++++++++rrrrrrrrrrrr777777777777MMMMMMMMMMMMIIIIIIIIIIII````````````''''''''''''{{{{{{{{{{{{",
"++++++++++++rrrrrrrrrrrr777777777777MMMMMMMMMMMMIIIIIIIIIIII````````````''''''''''''{{{{{{{{{{{{",
"++++++++++++rrrrrrrrrrrr777777777777MMMMMMMMMMMMIIIIIIIIIIII````````````''''''''''''{{{{{{{{{{{{",
"++++++++++++rrrrrrrrrrrr777777777777MMMMMMMMMMMMIIIIIIIIIIII````````````''''''''''''{{{{{{{{{{{{",
"------------$$$$$$$$$$$$999999999999JJJJJJJJJJJJTTTTTTTTTTTT____________]]]]]]]]]]]]{{{{{{{{{{{{",
"------------$$$$$$$$$$$$999999999999JJJJJJJJJJJJTTTTTTTTTTTT____________]]]]]]]]]]]]{{{{{{{{{{{{",
"------------$$$$$$$$$$$$999999999999JJJJJJJJJJJJTTTTTTTTTTTT____________]]]]]]]]]]]]{{{{{{{{{{{{",
"------------$$$$$$$$$$$$999999999999JJJJJJJJJJJJTTTTTTTTTTTT____________]]]]]]]]]]]]{{{{{{{{{{{{",
"------------$$$$$$$$$$$$999999999999JJJJJJJJJJJJTTTTTTTTTTTT____________]]]]]]]]]]]]{{{{{{{{{{{{",
"------------$$$$$$$$$$$$999999999999JJJJJJJJJJJJTTTTTTTTTTTT____________]]]]]]]]]]]]{{{{{{{{{{{{",
"------------$$$$$$$$$$$$999999999999JJJJJJJJJJJJTTTTTTTTTTTT____________]]]]]]]]]]]]{{{{{{{{{{{{",
"------------$$$$$$$$$$$$999999999999JJJJJJJJJJJJTTTTTTTTTTTT____________]]]]]]]]]]]]{{{{{{{{{{{{",
"------------$$$$$$$$$$$$999999999999JJJJJJJJJJJJTTTTTTTTTTTT____________]]]]]]]]]]]]{{{{{{{{{{{{",
"------------$$$$$$$$$$$$999999999999JJJJJJJJJJJJTTTTTTTTTTTT____________]]]]]]]]]]]]{{{{{{{{{{{{",
"------------$$$$$$$$$$$$999999999999JJJJJJJJJJJJTTTTTTTTTTTT____________]]]]]]]]]]]]{{{{{{{{{{{{",
"------------$$$$$$$$$$$$999999999999JJJJJJJJJJJJTTTTTTTTTTTT____________]]]]]]]]]]]]{{{{{{{{{{{{",
"@@@@@@@@@@@@666666666666ttttttttttttWWWWWWWWWWWWPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"@@@@@@@@@@@@666666666666ttttttttttttWWWWWWWWWWWWPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"@@@@@@@@@@@@666666666666ttttttttttttWWWWWWWWWWWWPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"@@@@@@@@@@@@666666666666ttttttttttttWWWWWWWWWWWWPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"@@@@@@@@@@@@666666666666ttttttttttttWWWWWWWWWWWWPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"@@@@@@@@@@@@666666666666ttttttttttttWWWWWWWWWWWWPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"@@@@@@@@@@@@666666666666ttttttttttttWWWWWWWWWWWWPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"@@@@@@@@@@@@666666666666ttttttttttttWWWWWWWWWWWWPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"@@@@@@@@@@@@666666666666ttttttttttttWWWWWWWWWWWWPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"@@@@@@@@@@@@666666666666ttttttttttttWWWWWWWWWWWWPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"@@@@@@@@@@@@666666666666ttttttttttttWWWWWWWWWWWWPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"@@@@@@@@@@@@666666666666ttttttttttttWWWWWWWWWWWWPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaazzzzzzzzzzzzBBBBBBBBBBBBbbbbbbbbbbbbPPPPPPPPPPPP____________''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaazzzzzzzzzzzzBBBBBBBBBBBBbbbbbbbbbbbbPPPPPPPPPPPP____________''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaazzzzzzzzzzzzBBBBBBBBBBBBbbbbbbbbbbbbPPPPPPPPPPPP____________''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaazzzzzzzzzzzzBBBBBBBBBBBBbbbbbbbbbbbbPPPPPPPPPPPP____________''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaazzzzzzzzzzzzBBBBBBBBBBBBbbbbbbbbbbbbPPPPPPPPPPPP____________''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaazzzzzzzzzzzzBBBBBBBBBBBBbbbbbbbbbbbbPPPPPPPPPPPP____________''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaazzzzzzzzzzzzBBBBBBBBBBBBbbbbbbbbbbbbPPPPPPPPPPPP____________''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaazzzzzzzzzzzzBBBBBBBBBBBBbbbbbbbbbbbbPPPPPPPPPPPP____________''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaazzzzzzzzzzzzBBBBBBBBBBBBbbbbbbbbbbbbPPPPPPPPPPPP____________''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaazzzzzzzzzzzzBBBBBBBBBBBBbbbbbbbbbbbbPPPPPPPPPPPP____________''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaazzzzzzzzzzzzBBBBBBBBBBBBbbbbbbbbbbbbPPPPPPPPPPPP____________''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaazzzzzzzzzzzzBBBBBBBBBBBBbbbbbbbbbbbbPPPPPPPPPPPP____________''''''''''''{{{{{{{{{{{{",
"------------%%%%%%%%%%%%ttttttttttttNNNNNNNNNNNN^^^^^^^^^^^^))))))))))))''''''''''''}}}}}}}}}}}}",
"------------%%%%%%%%%%%%ttttttttttttNNNNNNNNNNNN^^^^^^^^^^^^))))))))))))''''''''''''}}}}}}}}}}}}",
"------------%%%%%%%%%%%%ttttttttttttNNNNNNNNNNNN^^^^^^^^^^^^))))))))))))''''''''''''}}}}}}}}}}}}",
"------------%%%%%%%%%%%%ttttttttttttNNNNNNNNNNNN^^^^^^^^^^^^))))))))))))''''''''''''}}}}}}}}}}}}",
"------------%%%%%%%%%%%%ttttttttttttNNNNNNNNNNNN^^^^^^^^^^^^))))))))))))''''''''''''}}}}}}}}}}}}",
"------------%%%%%%%%%%%%ttttttttttttNNNNNNNNNNNN^^^^^^^^^^^^))))))))))))''''''''''''}}}}}}}}}}}}",
"------------%%%%%%%%%%%%ttttttttttttNNNNNNNNNNNN^^^^^^^^^^^^))))))))))))''''''''''''}}}}}}}}}}}}",
"------------%%%%%%%%%%%%ttttttttttttNNNNNNNNNNNN^^^^^^^^^^^^))))))))))))''''''''''''}}}}}}}}}}}}",
"------------%%%%%%%%%%%%ttttttttttttNNNNNNNNNNNN^^^^^^^^^^^^))))))))))))''''''''''''}}}}}}}}}}}}",
"------------%%%%%%%%%%%%ttttttttttttNNNNNNNNNNNN^^^^^^^^^^^^))))))))))))''''''''''''}}}}}}}}}}}}",
"------------%%%%%%%%%%%%ttttttttttttNNNNNNNNNNNN^^^^^^^^^^^^))))))))))))''''''''''''}}}}}}}}}}}}",
"------------%%%%%%%%%%%%ttttttttttttNNNNNNNNNNNN^^^^^^^^^^^^))))))))))))''''''''''''}}}}}}}}}}}}",
" 000000000000888888888888FFFFFFFFFFFF~~~~~~~~~~~~))))))))))))''''''''''''}}}}}}}}}}}}",
" 000000000000888888888888FFFFFFFFFFFF~~~~~~~~~~~~))))))))))))''''''''''''}}}}}}}}}}}}",
" 000000000000888888888888FFFFFFFFFFFF~~~~~~~~~~~~))))))))))))''''''''''''}}}}}}}}}}}}",
" 000000000000888888888888FFFFFFFFFFFF~~~~~~~~~~~~))))))))))))''''''''''''}}}}}}}}}}}}",
" 000000000000888888888888FFFFFFFFFFFF~~~~~~~~~~~~))))))))))))''''''''''''}}}}}}}}}}}}",
" 000000000000888888888888FFFFFFFFFFFF~~~~~~~~~~~~))))))))))))''''''''''''}}}}}}}}}}}}",
" 000000000000888888888888FFFFFFFFFFFF~~~~~~~~~~~~))))))))))))''''''''''''}}}}}}}}}}}}",
" 000000000000888888888888FFFFFFFFFFFF~~~~~~~~~~~~))))))))))))''''''''''''}}}}}}}}}}}}",
" 000000000000888888888888FFFFFFFFFFFF~~~~~~~~~~~~))))))))))))''''''''''''}}}}}}}}}}}}",
" 000000000000888888888888FFFFFFFFFFFF~~~~~~~~~~~~))))))))))))''''''''''''}}}}}}}}}}}}",
" 000000000000888888888888FFFFFFFFFFFF~~~~~~~~~~~~))))))))))))''''''''''''}}}}}}}}}}}}",
" 000000000000888888888888FFFFFFFFFFFF~~~~~~~~~~~~))))))))))))''''''''''''}}}}}}}}}}}}",
"++++++++++++222222222222xxxxxxxxxxxxNNNNNNNNNNNNEEEEEEEEEEEE))))))))))))''''''''''''}}}}}}}}}}}}",
"++++++++++++222222222222xxxxxxxxxxxxNNNNNNNNNNNNEEEEEEEEEEEE))))))))))))''''''''''''}}}}}}}}}}}}",
"++++++++++++222222222222xxxxxxxxxxxxNNNNNNNNNNNNEEEEEEEEEEEE))))))))))))''''''''''''}}}}}}}}}}}}",
"++++++++++++222222222222xxxxxxxxxxxxNNNNNNNNNNNNEEEEEEEEEEEE))))))))))))''''''''''''}}}}}}}}}}}}",
"++++++++++++222222222222xxxxxxxxxxxxNNNNNNNNNNNNEEEEEEEEEEEE))))))))))))''''''''''''}}}}}}}}}}}}",
"++++++++++++222222222222xxxxxxxxxxxxNNNNNNNNNNNNEEEEEEEEEEEE))))))))))))''''''''''''}}}}}}}}}}}}",
"++++++++++++222222222222xxxxxxxxxxxxNNNNNNNNNNNNEEEEEEEEEEEE))))))))))))''''''''''''}}}}}}}}}}}}",
"++++++++++++222222222222xxxxxxxxxxxxNNNNNNNNNNNNEEEEEEEEEEEE))))))))))))''''''''''''}}}}}}}}}}}}",
"++++++++++++222222222222xxxxxxxxxxxxNNNNNNNNNNNNEEEEEEEEEEEE))))))))))))''''''''''''}}}}}}}}}}}}",
"++++++++++++222222222222xxxxxxxxxxxxNNNNNNNNNNNNEEEEEEEEEEEE))))))))))))''''''''''''}}}}}}}}}}}}",
"++++++++++++222222222222xxxxxxxxxxxxNNNNNNNNNNNNEEEEEEEEEEEE))))))))))))''''''''''''}}}}}}}}}}}}",
"++++++++++++222222222222xxxxxxxxxxxxNNNNNNNNNNNNEEEEEEEEEEEE))))))))))))''''''''''''}}}}}}}}}}}}",
"$$$$$$$$$$$$000000000000GGGGGGGGGGGGnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"$$$$$$$$$$$$000000000000GGGGGGGGGGGGnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"$$$$$$$$$$$$000000000000GGGGGGGGGGGGnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"$$$$$$$$$$$$000000000000GGGGGGGGGGGGnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"$$$$$$$$$$$$000000000000GGGGGGGGGGGGnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"$$$$$$$$$$$$000000000000GGGGGGGGGGGGnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"$$$$$$$$$$$$000000000000GGGGGGGGGGGGnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"$$$$$$$$$$$$000000000000GGGGGGGGGGGGnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"$$$$$$$$$$$$000000000000GGGGGGGGGGGGnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"$$$$$$$$$$$$000000000000GGGGGGGGGGGGnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"$$$$$$$$$$$$000000000000GGGGGGGGGGGGnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"$$$$$$$$$$$$000000000000GGGGGGGGGGGGnnnnnnnnnnnnLLLLLLLLLLLL))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ooooooooooooffffffffffffccccccccccccbbbbbbbbbbbbRRRRRRRRRRRR____________''''''''''''{{{{{{{{{{{{",
"ooooooooooooffffffffffffccccccccccccbbbbbbbbbbbbRRRRRRRRRRRR____________''''''''''''{{{{{{{{{{{{",
"ooooooooooooffffffffffffccccccccccccbbbbbbbbbbbbRRRRRRRRRRRR____________''''''''''''{{{{{{{{{{{{",
"ooooooooooooffffffffffffccccccccccccbbbbbbbbbbbbRRRRRRRRRRRR____________''''''''''''{{{{{{{{{{{{",
"ooooooooooooffffffffffffccccccccccccbbbbbbbbbbbbRRRRRRRRRRRR____________''''''''''''{{{{{{{{{{{{",
"ooooooooooooffffffffffffccccccccccccbbbbbbbbbbbbRRRRRRRRRRRR____________''''''''''''{{{{{{{{{{{{",
"ooooooooooooffffffffffffccccccccccccbbbbbbbbbbbbRRRRRRRRRRRR____________''''''''''''{{{{{{{{{{{{",
"ooooooooooooffffffffffffccccccccccccbbbbbbbbbbbbRRRRRRRRRRRR____________''''''''''''{{{{{{{{{{{{",
"ooooooooooooffffffffffffccccccccccccbbbbbbbbbbbbRRRRRRRRRRRR____________''''''''''''{{{{{{{{{{{{",
"ooooooooooooffffffffffffccccccccccccbbbbbbbbbbbbRRRRRRRRRRRR____________''''''''''''{{{{{{{{{{{{",
"ooooooooooooffffffffffffccccccccccccbbbbbbbbbbbbRRRRRRRRRRRR____________''''''''''''{{{{{{{{{{{{",
"ooooooooooooffffffffffffccccccccccccbbbbbbbbbbbbRRRRRRRRRRRR____________''''''''''''{{{{{{{{{{{{",
"@@@@@@@@@@@@111111111111777777777777JJJJJJJJJJJJPPPPPPPPPPPP((((((((((((''''''''''''{{{{{{{{{{{{",
"@@@@@@@@@@@@111111111111777777777777JJJJJJJJJJJJPPPPPPPPPPPP((((((((((((''''''''''''{{{{{{{{{{{{",
"@@@@@@@@@@@@111111111111777777777777JJJJJJJJJJJJPPPPPPPPPPPP((((((((((((''''''''''''{{{{{{{{{{{{",
"@@@@@@@@@@@@111111111111777777777777JJJJJJJJJJJJPPPPPPPPPPPP((((((((((((''''''''''''{{{{{{{{{{{{",
"@@@@@@@@@@@@111111111111777777777777JJJJJJJJJJJJPPPPPPPPPPPP((((((((((((''''''''''''{{{{{{{{{{{{",
"@@@@@@@@@@@@111111111111777777777777JJJJJJJJJJJJPPPPPPPPPPPP((((((((((((''''''''''''{{{{{{{{{{{{",
"@@@@@@@@@@@@111111111111777777777777JJJJJJJJJJJJPPPPPPPPPPPP((((((((((((''''''''''''{{{{{{{{{{{{",
"@@@@@@@@@@@@111111111111777777777777JJJJJJJJJJJJPPPPPPPPPPPP((((((((((((''''''''''''{{{{{{{{{{{{",
"@@@@@@@@@@@@111111111111777777777777JJJJJJJJJJJJPPPPPPPPPPPP((((((((((((''''''''''''{{{{{{{{{{{{",
"@@@@@@@@@@@@111111111111777777777777JJJJJJJJJJJJPPPPPPPPPPPP((((((((((((''''''''''''{{{{{{{{{{{{",
"@@@@@@@@@@@@111111111111777777777777JJJJJJJJJJJJPPPPPPPPPPPP((((((((((((''''''''''''{{{{{{{{{{{{",
"@@@@@@@@@@@@111111111111777777777777JJJJJJJJJJJJPPPPPPPPPPPP((((((((((((''''''''''''{{{{{{{{{{{{",
" iiiiiiiiiiiiGGGGGGGGGGGGVVVVVVVVVVVV~~~~~~~~~~~~____________''''''''''''}}}}}}}}}}}}",
" iiiiiiiiiiiiGGGGGGGGGGGGVVVVVVVVVVVV~~~~~~~~~~~~____________''''''''''''}}}}}}}}}}}}",
" iiiiiiiiiiiiGGGGGGGGGGGGVVVVVVVVVVVV~~~~~~~~~~~~____________''''''''''''}}}}}}}}}}}}",
" iiiiiiiiiiiiGGGGGGGGGGGGVVVVVVVVVVVV~~~~~~~~~~~~____________''''''''''''}}}}}}}}}}}}",
" iiiiiiiiiiiiGGGGGGGGGGGGVVVVVVVVVVVV~~~~~~~~~~~~____________''''''''''''}}}}}}}}}}}}",
" iiiiiiiiiiiiGGGGGGGGGGGGVVVVVVVVVVVV~~~~~~~~~~~~____________''''''''''''}}}}}}}}}}}}",
" iiiiiiiiiiiiGGGGGGGGGGGGVVVVVVVVVVVV~~~~~~~~~~~~____________''''''''''''}}}}}}}}}}}}",
" iiiiiiiiiiiiGGGGGGGGGGGGVVVVVVVVVVVV~~~~~~~~~~~~____________''''''''''''}}}}}}}}}}}}",
" iiiiiiiiiiiiGGGGGGGGGGGGVVVVVVVVVVVV~~~~~~~~~~~~____________''''''''''''}}}}}}}}}}}}",
" iiiiiiiiiiiiGGGGGGGGGGGGVVVVVVVVVVVV~~~~~~~~~~~~____________''''''''''''}}}}}}}}}}}}",
" iiiiiiiiiiiiGGGGGGGGGGGGVVVVVVVVVVVV~~~~~~~~~~~~____________''''''''''''}}}}}}}}}}}}",
" iiiiiiiiiiiiGGGGGGGGGGGGVVVVVVVVVVVV~~~~~~~~~~~~____________''''''''''''}}}}}}}}}}}}",
"------------222222222222KKKKKKKKKKKKIIIIIIIIIIIIQQQQQQQQQQQQ____________''''''''''''{{{{{{{{{{{{",
"------------222222222222KKKKKKKKKKKKIIIIIIIIIIIIQQQQQQQQQQQQ____________''''''''''''{{{{{{{{{{{{",
"------------222222222222KKKKKKKKKKKKIIIIIIIIIIIIQQQQQQQQQQQQ____________''''''''''''{{{{{{{{{{{{",
"------------222222222222KKKKKKKKKKKKIIIIIIIIIIIIQQQQQQQQQQQQ____________''''''''''''{{{{{{{{{{{{",
"------------222222222222KKKKKKKKKKKKIIIIIIIIIIIIQQQQQQQQQQQQ____________''''''''''''{{{{{{{{{{{{",
"------------222222222222KKKKKKKKKKKKIIIIIIIIIIIIQQQQQQQQQQQQ____________''''''''''''{{{{{{{{{{{{",
"------------222222222222KKKKKKKKKKKKIIIIIIIIIIIIQQQQQQQQQQQQ____________''''''''''''{{{{{{{{{{{{",
"------------222222222222KKKKKKKKKKKKIIIIIIIIIIIIQQQQQQQQQQQQ____________''''''''''''{{{{{{{{{{{{",
"------------222222222222KKKKKKKKKKKKIIIIIIIIIIIIQQQQQQQQQQQQ____________''''''''''''{{{{{{{{{{{{",
"------------222222222222KKKKKKKKKKKKIIIIIIIIIIIIQQQQQQQQQQQQ____________''''''''''''{{{{{{{{{{{{",
"------------222222222222KKKKKKKKKKKKIIIIIIIIIIIIQQQQQQQQQQQQ____________''''''''''''{{{{{{{{{{{{",
"------------222222222222KKKKKKKKKKKKIIIIIIIIIIIIQQQQQQQQQQQQ____________''''''''''''{{{{{{{{{{{{",
"&&&&&&&&&&&&222222222222333333333333WWWWWWWWWWWW~~~~~~~~~~~~____________''''''''''''{{{{{{{{{{{{",
"&&&&&&&&&&&&222222222222333333333333WWWWWWWWWWWW~~~~~~~~~~~~____________''''''''''''{{{{{{{{{{{{",
"&&&&&&&&&&&&222222222222333333333333WWWWWWWWWWWW~~~~~~~~~~~~____________''''''''''''{{{{{{{{{{{{",
"&&&&&&&&&&&&222222222222333333333333WWWWWWWWWWWW~~~~~~~~~~~~____________''''''''''''{{{{{{{{{{{{",
"&&&&&&&&&&&&222222222222333333333333WWWWWWWWWWWW~~~~~~~~~~~~____________''''''''''''{{{{{{{{{{{{",
"&&&&&&&&&&&&222222222222333333333333WWWWWWWWWWWW~~~~~~~~~~~~____________''''''''''''{{{{{{{{{{{{",
"&&&&&&&&&&&&222222222222333333333333WWWWWWWWWWWW~~~~~~~~~~~~____________''''''''''''{{{{{{{{{{{{",
"&&&&&&&&&&&&222222222222333333333333WWWWWWWWWWWW~~~~~~~~~~~~____________''''''''''''{{{{{{{{{{{{",
"&&&&&&&&&&&&222222222222333333333333WWWWWWWWWWWW~~~~~~~~~~~~____________''''''''''''{{{{{{{{{{{{",
"&&&&&&&&&&&&222222222222333333333333WWWWWWWWWWWW~~~~~~~~~~~~____________''''''''''''{{{{{{{{{{{{",
"&&&&&&&&&&&&222222222222333333333333WWWWWWWWWWWW~~~~~~~~~~~~____________''''''''''''{{{{{{{{{{{{",
"&&&&&&&&&&&&222222222222333333333333WWWWWWWWWWWW~~~~~~~~~~~~____________''''''''''''{{{{{{{{{{{{",
"wwwwwwwwwwww============555555555555EEEEEEEEEEEEEEEEEEEEEEEE____________''''''''''''||||||||||||",
"wwwwwwwwwwww============555555555555EEEEEEEEEEEEEEEEEEEEEEEE____________''''''''''''||||||||||||",
"wwwwwwwwwwww============555555555555EEEEEEEEEEEEEEEEEEEEEEEE____________''''''''''''||||||||||||",
"wwwwwwwwwwww============555555555555EEEEEEEEEEEEEEEEEEEEEEEE____________''''''''''''||||||||||||",
"wwwwwwwwwwww============555555555555EEEEEEEEEEEEEEEEEEEEEEEE____________''''''''''''||||||||||||",
"wwwwwwwwwwww============555555555555EEEEEEEEEEEEEEEEEEEEEEEE____________''''''''''''||||||||||||",
"wwwwwwwwwwww============555555555555EEEEEEEEEEEEEEEEEEEEEEEE____________''''''''''''||||||||||||",
"wwwwwwwwwwww============555555555555EEEEEEEEEEEEEEEEEEEEEEEE____________''''''''''''||||||||||||",
"wwwwwwwwwwww============555555555555EEEEEEEEEEEEEEEEEEEEEEEE____________''''''''''''||||||||||||",
"wwwwwwwwwwww============555555555555EEEEEEEEEEEEEEEEEEEEEEEE____________''''''''''''||||||||||||",
"wwwwwwwwwwww============555555555555EEEEEEEEEEEEEEEEEEEEEEEE____________''''''''''''||||||||||||",
"wwwwwwwwwwww============555555555555EEEEEEEEEEEEEEEEEEEEEEEE____________''''''''''''||||||||||||",
"ffffffffffff>>>>>>>>>>>>rrrrrrrrrrrrnnnnnnnnnnnn~~~~~~~~~~~~____________]]]]]]]]]]]]{{{{{{{{{{{{",
"ffffffffffff>>>>>>>>>>>>rrrrrrrrrrrrnnnnnnnnnnnn~~~~~~~~~~~~____________]]]]]]]]]]]]{{{{{{{{{{{{",
"ffffffffffff>>>>>>>>>>>>rrrrrrrrrrrrnnnnnnnnnnnn~~~~~~~~~~~~____________]]]]]]]]]]]]{{{{{{{{{{{{",
"ffffffffffff>>>>>>>>>>>>rrrrrrrrrrrrnnnnnnnnnnnn~~~~~~~~~~~~____________]]]]]]]]]]]]{{{{{{{{{{{{",
"ffffffffffff>>>>>>>>>>>>rrrrrrrrrrrrnnnnnnnnnnnn~~~~~~~~~~~~____________]]]]]]]]]]]]{{{{{{{{{{{{",
"ffffffffffff>>>>>>>>>>>>rrrrrrrrrrrrnnnnnnnnnnnn~~~~~~~~~~~~____________]]]]]]]]]]]]{{{{{{{{{{{{",
"ffffffffffff>>>>>>>>>>>>rrrrrrrrrrrrnnnnnnnnnnnn~~~~~~~~~~~~____________]]]]]]]]]]]]{{{{{{{{{{{{",
"ffffffffffff>>>>>>>>>>>>rrrrrrrrrrrrnnnnnnnnnnnn~~~~~~~~~~~~____________]]]]]]]]]]]]{{{{{{{{{{{{",
"ffffffffffff>>>>>>>>>>>>rrrrrrrrrrrrnnnnnnnnnnnn~~~~~~~~~~~~____________]]]]]]]]]]]]{{{{{{{{{{{{",
"ffffffffffff>>>>>>>>>>>>rrrrrrrrrrrrnnnnnnnnnnnn~~~~~~~~~~~~____________]]]]]]]]]]]]{{{{{{{{{{{{",
"ffffffffffff>>>>>>>>>>>>rrrrrrrrrrrrnnnnnnnnnnnn~~~~~~~~~~~~____________]]]]]]]]]]]]{{{{{{{{{{{{",
"ffffffffffff>>>>>>>>>>>>rrrrrrrrrrrrnnnnnnnnnnnn~~~~~~~~~~~~____________]]]]]]]]]]]]{{{{{{{{{{{{",
"############$$$$$$$$$$$$CCCCCCCCCCCCEEEEEEEEEEEE(((((((((((())))))))))))''''''''''''}}}}}}}}}}}}",
"############$$$$$$$$$$$$CCCCCCCCCCCCEEEEEEEEEEEE(((((((((((())))))))))))''''''''''''}}}}}}}}}}}}",
"############$$$$$$$$$$$$CCCCCCCCCCCCEEEEEEEEEEEE(((((((((((())))))))))))''''''''''''}}}}}}}}}}}}",
"############$$$$$$$$$$$$CCCCCCCCCCCCEEEEEEEEEEEE(((((((((((())))))))))))''''''''''''}}}}}}}}}}}}",
"############$$$$$$$$$$$$CCCCCCCCCCCCEEEEEEEEEEEE(((((((((((())))))))))))''''''''''''}}}}}}}}}}}}",
"############$$$$$$$$$$$$CCCCCCCCCCCCEEEEEEEEEEEE(((((((((((())))))))))))''''''''''''}}}}}}}}}}}}",
"############$$$$$$$$$$$$CCCCCCCCCCCCEEEEEEEEEEEE(((((((((((())))))))))))''''''''''''}}}}}}}}}}}}",
"############$$$$$$$$$$$$CCCCCCCCCCCCEEEEEEEEEEEE(((((((((((())))))))))))''''''''''''}}}}}}}}}}}}",
"############$$$$$$$$$$$$CCCCCCCCCCCCEEEEEEEEEEEE(((((((((((())))))))))))''''''''''''}}}}}}}}}}}}",
"############$$$$$$$$$$$$CCCCCCCCCCCCEEEEEEEEEEEE(((((((((((())))))))))))''''''''''''}}}}}}}}}}}}",
"############$$$$$$$$$$$$CCCCCCCCCCCCEEEEEEEEEEEE(((((((((((())))))))))))''''''''''''}}}}}}}}}}}}",
"############$$$$$$$$$$$$CCCCCCCCCCCCEEEEEEEEEEEE(((((((((((())))))))))))''''''''''''}}}}}}}}}}}}",
",,,,,,,,,,,,666666666666ddddddddddddHHHHHHHHHHHHEEEEEEEEEEEE____________]]]]]]]]]]]]{{{{{{{{{{{{",
",,,,,,,,,,,,666666666666ddddddddddddHHHHHHHHHHHHEEEEEEEEEEEE____________]]]]]]]]]]]]{{{{{{{{{{{{",
",,,,,,,,,,,,666666666666ddddddddddddHHHHHHHHHHHHEEEEEEEEEEEE____________]]]]]]]]]]]]{{{{{{{{{{{{",
",,,,,,,,,,,,666666666666ddddddddddddHHHHHHHHHHHHEEEEEEEEEEEE____________]]]]]]]]]]]]{{{{{{{{{{{{",
",,,,,,,,,,,,666666666666ddddddddddddHHHHHHHHHHHHEEEEEEEEEEEE____________]]]]]]]]]]]]{{{{{{{{{{{{",
",,,,,,,,,,,,666666666666ddddddddddddHHHHHHHHHHHHEEEEEEEEEEEE____________]]]]]]]]]]]]{{{{{{{{{{{{",
",,,,,,,,,,,,666666666666ddddddddddddHHHHHHHHHHHHEEEEEEEEEEEE____________]]]]]]]]]]]]{{{{{{{{{{{{",
",,,,,,,,,,,,666666666666ddddddddddddHHHHHHHHHHHHEEEEEEEEEEEE____________]]]]]]]]]]]]{{{{{{{{{{{{",
",,,,,,,,,,,,666666666666ddddddddddddHHHHHHHHHHHHEEEEEEEEEEEE____________]]]]]]]]]]]]{{{{{{{{{{{{",
",,,,,,,,,,,,666666666666ddddddddddddHHHHHHHHHHHHEEEEEEEEEEEE____________]]]]]]]]]]]]{{{{{{{{{{{{",
",,,,,,,,,,,,666666666666ddddddddddddHHHHHHHHHHHHEEEEEEEEEEEE____________]]]]]]]]]]]]{{{{{{{{{{{{",
",,,,,,,,,,,,666666666666ddddddddddddHHHHHHHHHHHHEEEEEEEEEEEE____________]]]]]]]]]]]]{{{{{{{{{{{{",
"xxxxxxxxxxxxjjjjjjjjjjjjccccccccccccSSSSSSSSSSSSPPPPPPPPPPPP))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"xxxxxxxxxxxxjjjjjjjjjjjjccccccccccccSSSSSSSSSSSSPPPPPPPPPPPP))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"xxxxxxxxxxxxjjjjjjjjjjjjccccccccccccSSSSSSSSSSSSPPPPPPPPPPPP))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"xxxxxxxxxxxxjjjjjjjjjjjjccccccccccccSSSSSSSSSSSSPPPPPPPPPPPP))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"xxxxxxxxxxxxjjjjjjjjjjjjccccccccccccSSSSSSSSSSSSPPPPPPPPPPPP))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"xxxxxxxxxxxxjjjjjjjjjjjjccccccccccccSSSSSSSSSSSSPPPPPPPPPPPP))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"xxxxxxxxxxxxjjjjjjjjjjjjccccccccccccSSSSSSSSSSSSPPPPPPPPPPPP))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"xxxxxxxxxxxxjjjjjjjjjjjjccccccccccccSSSSSSSSSSSSPPPPPPPPPPPP))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"xxxxxxxxxxxxjjjjjjjjjjjjccccccccccccSSSSSSSSSSSSPPPPPPPPPPPP))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"xxxxxxxxxxxxjjjjjjjjjjjjccccccccccccSSSSSSSSSSSSPPPPPPPPPPPP))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"xxxxxxxxxxxxjjjjjjjjjjjjccccccccccccSSSSSSSSSSSSPPPPPPPPPPPP))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"xxxxxxxxxxxxjjjjjjjjjjjjccccccccccccSSSSSSSSSSSSPPPPPPPPPPPP))))))))))))]]]]]]]]]]]]}}}}}}}}}}}}",
"000000000000%%%%%%%%%%%%ttttttttttttmmmmmmmmmmmm////////////````````````''''''''''''{{{{{{{{{{{{",
"000000000000%%%%%%%%%%%%ttttttttttttmmmmmmmmmmmm////////////````````````''''''''''''{{{{{{{{{{{{",
"000000000000%%%%%%%%%%%%ttttttttttttmmmmmmmmmmmm////////////````````````''''''''''''{{{{{{{{{{{{",
"000000000000%%%%%%%%%%%%ttttttttttttmmmmmmmmmmmm////////////````````````''''''''''''{{{{{{{{{{{{",
"000000000000%%%%%%%%%%%%ttttttttttttmmmmmmmmmmmm////////////````````````''''''''''''{{{{{{{{{{{{",
"000000000000%%%%%%%%%%%%ttttttttttttmmmmmmmmmmmm////////////````````````''''''''''''{{{{{{{{{{{{",
"000000000000%%%%%%%%%%%%ttttttttttttmmmmmmmmmmmm////////////````````````''''''''''''{{{{{{{{{{{{",
"000000000000%%%%%%%%%%%%ttttttttttttmmmmmmmmmmmm////////////````````````''''''''''''{{{{{{{{{{{{",
"000000000000%%%%%%%%%%%%ttttttttttttmmmmmmmmmmmm////////////````````````''''''''''''{{{{{{{{{{{{",
"000000000000%%%%%%%%%%%%ttttttttttttmmmmmmmmmmmm////////////````````````''''''''''''{{{{{{{{{{{{",
"000000000000%%%%%%%%%%%%ttttttttttttmmmmmmmmmmmm////////////````````````''''''''''''{{{{{{{{{{{{",
"000000000000%%%%%%%%%%%%ttttttttttttmmmmmmmmmmmm////////////````````````''''''''''''{{{{{{{{{{{{",
">>>>>>>>>>>>uuuuuuuuuuuuZZZZZZZZZZZZmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
">>>>>>>>>>>>uuuuuuuuuuuuZZZZZZZZZZZZmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
">>>>>>>>>>>>uuuuuuuuuuuuZZZZZZZZZZZZmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
">>>>>>>>>>>>uuuuuuuuuuuuZZZZZZZZZZZZmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
">>>>>>>>>>>>uuuuuuuuuuuuZZZZZZZZZZZZmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
">>>>>>>>>>>>uuuuuuuuuuuuZZZZZZZZZZZZmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
">>>>>>>>>>>>uuuuuuuuuuuuZZZZZZZZZZZZmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
">>>>>>>>>>>>uuuuuuuuuuuuZZZZZZZZZZZZmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
">>>>>>>>>>>>uuuuuuuuuuuuZZZZZZZZZZZZmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
">>>>>>>>>>>>uuuuuuuuuuuuZZZZZZZZZZZZmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
">>>>>>>>>>>>uuuuuuuuuuuuZZZZZZZZZZZZmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
">>>>>>>>>>>>uuuuuuuuuuuuZZZZZZZZZZZZmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''{{{{{{{{{{{{",
"OOOOOOOOOOOO444444444444888888888888KKKKKKKKKKKKTTTTTTTTTTTT))))))))))))''''''''''''{{{{{{{{{{{{",
"OOOOOOOOOOOO444444444444888888888888KKKKKKKKKKKKTTTTTTTTTTTT))))))))))))''''''''''''{{{{{{{{{{{{",
"OOOOOOOOOOOO444444444444888888888888KKKKKKKKKKKKTTTTTTTTTTTT))))))))))))''''''''''''{{{{{{{{{{{{",
"OOOOOOOOOOOO444444444444888888888888KKKKKKKKKKKKTTTTTTTTTTTT))))))))))))''''''''''''{{{{{{{{{{{{",
"OOOOOOOOOOOO444444444444888888888888KKKKKKKKKKKKTTTTTTTTTTTT))))))))))))''''''''''''{{{{{{{{{{{{",
"OOOOOOOOOOOO444444444444888888888888KKKKKKKKKKKKTTTTTTTTTTTT))))))))))))''''''''''''{{{{{{{{{{{{",
"OOOOOOOOOOOO444444444444888888888888KKKKKKKKKKKKTTTTTTTTTTTT))))))))))))''''''''''''{{{{{{{{{{{{",
"OOOOOOOOOOOO444444444444888888888888KKKKKKKKKKKKTTTTTTTTTTTT))))))))))))''''''''''''{{{{{{{{{{{{",
"OOOOOOOOOOOO444444444444888888888888KKKKKKKKKKKKTTTTTTTTTTTT))))))))))))''''''''''''{{{{{{{{{{{{",
"OOOOOOOOOOOO444444444444888888888888KKKKKKKKKKKKTTTTTTTTTTTT))))))))))))''''''''''''{{{{{{{{{{{{",
"OOOOOOOOOOOO444444444444888888888888KKKKKKKKKKKKTTTTTTTTTTTT))))))))))))''''''''''''{{{{{{{{{{{{",
"OOOOOOOOOOOO444444444444888888888888KKKKKKKKKKKKTTTTTTTTTTTT))))))))))))''''''''''''{{{{{{{{{{{{",
"++++++++++++666666666666CCCCCCCCCCCCQQQQQQQQQQQQYYYYYYYYYYYY____________''''''''''''}}}}}}}}}}}}",
"++++++++++++666666666666CCCCCCCCCCCCQQQQQQQQQQQQYYYYYYYYYYYY____________''''''''''''}}}}}}}}}}}}",
"++++++++++++666666666666CCCCCCCCCCCCQQQQQQQQQQQQYYYYYYYYYYYY____________''''''''''''}}}}}}}}}}}}",
"++++++++++++666666666666CCCCCCCCCCCCQQQQQQQQQQQQYYYYYYYYYYYY____________''''''''''''}}}}}}}}}}}}",
"++++++++++++666666666666CCCCCCCCCCCCQQQQQQQQQQQQYYYYYYYYYYYY____________''''''''''''}}}}}}}}}}}}",
"++++++++++++666666666666CCCCCCCCCCCCQQQQQQQQQQQQYYYYYYYYYYYY____________''''''''''''}}}}}}}}}}}}",
"++++++++++++666666666666CCCCCCCCCCCCQQQQQQQQQQQQYYYYYYYYYYYY____________''''''''''''}}}}}}}}}}}}",
"++++++++++++666666666666CCCCCCCCCCCCQQQQQQQQQQQQYYYYYYYYYYYY____________''''''''''''}}}}}}}}}}}}",
"++++++++++++666666666666CCCCCCCCCCCCQQQQQQQQQQQQYYYYYYYYYYYY____________''''''''''''}}}}}}}}}}}}",
"++++++++++++666666666666CCCCCCCCCCCCQQQQQQQQQQQQYYYYYYYYYYYY____________''''''''''''}}}}}}}}}}}}",
"++++++++++++666666666666CCCCCCCCCCCCQQQQQQQQQQQQYYYYYYYYYYYY____________''''''''''''}}}}}}}}}}}}",
"++++++++++++666666666666CCCCCCCCCCCCQQQQQQQQQQQQYYYYYYYYYYYY____________''''''''''''}}}}}}}}}}}}",
"oooooooooooo,,,,,,,,,,,,DDDDDDDDDDDDmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''}}}}}}}}}}}}",
"oooooooooooo,,,,,,,,,,,,DDDDDDDDDDDDmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''}}}}}}}}}}}}",
"oooooooooooo,,,,,,,,,,,,DDDDDDDDDDDDmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''}}}}}}}}}}}}",
"oooooooooooo,,,,,,,,,,,,DDDDDDDDDDDDmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''}}}}}}}}}}}}",
"oooooooooooo,,,,,,,,,,,,DDDDDDDDDDDDmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''}}}}}}}}}}}}",
"oooooooooooo,,,,,,,,,,,,DDDDDDDDDDDDmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''}}}}}}}}}}}}",
"oooooooooooo,,,,,,,,,,,,DDDDDDDDDDDDmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''}}}}}}}}}}}}",
"oooooooooooo,,,,,,,,,,,,DDDDDDDDDDDDmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''}}}}}}}}}}}}",
"oooooooooooo,,,,,,,,,,,,DDDDDDDDDDDDmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''}}}}}}}}}}}}",
"oooooooooooo,,,,,,,,,,,,DDDDDDDDDDDDmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''}}}}}}}}}}}}",
"oooooooooooo,,,,,,,,,,,,DDDDDDDDDDDDmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''}}}}}}}}}}}}",
"oooooooooooo,,,,,,,,,,,,DDDDDDDDDDDDmmmmmmmmmmmmLLLLLLLLLLLL))))))))))))''''''''''''}}}}}}}}}}}}",
"::::::::::::eeeeeeeeeeee444444444444mmmmmmmmmmmm^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"::::::::::::eeeeeeeeeeee444444444444mmmmmmmmmmmm^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"::::::::::::eeeeeeeeeeee444444444444mmmmmmmmmmmm^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"::::::::::::eeeeeeeeeeee444444444444mmmmmmmmmmmm^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"::::::::::::eeeeeeeeeeee444444444444mmmmmmmmmmmm^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"::::::::::::eeeeeeeeeeee444444444444mmmmmmmmmmmm^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"::::::::::::eeeeeeeeeeee444444444444mmmmmmmmmmmm^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"::::::::::::eeeeeeeeeeee444444444444mmmmmmmmmmmm^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"::::::::::::eeeeeeeeeeee444444444444mmmmmmmmmmmm^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"::::::::::::eeeeeeeeeeee444444444444mmmmmmmmmmmm^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"::::::::::::eeeeeeeeeeee444444444444mmmmmmmmmmmm^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"::::::::::::eeeeeeeeeeee444444444444mmmmmmmmmmmm^^^^^^^^^^^^____________''''''''''''{{{{{{{{{{{{",
"............666666666666ZZZZZZZZZZZZbbbbbbbbbbbbPPPPPPPPPPPP````````````''''''''''''{{{{{{{{{{{{",
"............666666666666ZZZZZZZZZZZZbbbbbbbbbbbbPPPPPPPPPPPP````````````''''''''''''{{{{{{{{{{{{",
"............666666666666ZZZZZZZZZZZZbbbbbbbbbbbbPPPPPPPPPPPP````````````''''''''''''{{{{{{{{{{{{",
"............666666666666ZZZZZZZZZZZZbbbbbbbbbbbbPPPPPPPPPPPP````````````''''''''''''{{{{{{{{{{{{",
"............666666666666ZZZZZZZZZZZZbbbbbbbbbbbbPPPPPPPPPPPP````````````''''''''''''{{{{{{{{{{{{",
"............666666666666ZZZZZZZZZZZZbbbbbbbbbbbbPPPPPPPPPPPP````````````''''''''''''{{{{{{{{{{{{",
"............666666666666ZZZZZZZZZZZZbbbbbbbbbbbbPPPPPPPPPPPP````````````''''''''''''{{{{{{{{{{{{",
"............666666666666ZZZZZZZZZZZZbbbbbbbbbbbbPPPPPPPPPPPP````````````''''''''''''{{{{{{{{{{{{",
"............666666666666ZZZZZZZZZZZZbbbbbbbbbbbbPPPPPPPPPPPP````````````''''''''''''{{{{{{{{{{{{",
"............666666666666ZZZZZZZZZZZZbbbbbbbbbbbbPPPPPPPPPPPP````````````''''''''''''{{{{{{{{{{{{",
"............666666666666ZZZZZZZZZZZZbbbbbbbbbbbbPPPPPPPPPPPP````````````''''''''''''{{{{{{{{{{{{",
"............666666666666ZZZZZZZZZZZZbbbbbbbbbbbbPPPPPPPPPPPP````````````''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaaiiiiiiiiiiiizzzzzzzzzzzzJJJJJJJJJJJJPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaaiiiiiiiiiiiizzzzzzzzzzzzJJJJJJJJJJJJPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaaiiiiiiiiiiiizzzzzzzzzzzzJJJJJJJJJJJJPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaaiiiiiiiiiiiizzzzzzzzzzzzJJJJJJJJJJJJPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaaiiiiiiiiiiiizzzzzzzzzzzzJJJJJJJJJJJJPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaaiiiiiiiiiiiizzzzzzzzzzzzJJJJJJJJJJJJPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaaiiiiiiiiiiiizzzzzzzzzzzzJJJJJJJJJJJJPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaaiiiiiiiiiiiizzzzzzzzzzzzJJJJJJJJJJJJPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaaiiiiiiiiiiiizzzzzzzzzzzzJJJJJJJJJJJJPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaaiiiiiiiiiiiizzzzzzzzzzzzJJJJJJJJJJJJPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaaiiiiiiiiiiiizzzzzzzzzzzzJJJJJJJJJJJJPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"aaaaaaaaaaaaiiiiiiiiiiiizzzzzzzzzzzzJJJJJJJJJJJJPPPPPPPPPPPP))))))))))))''''''''''''{{{{{{{{{{{{",
"............eeeeeeeeeeee444444444444IIIIIIIIIIIIWWWWWWWWWWWW))))))))))))''''''''''''}}}}}}}}}}}}",
"............eeeeeeeeeeee444444444444IIIIIIIIIIIIWWWWWWWWWWWW))))))))))))''''''''''''}}}}}}}}}}}}",
"............eeeeeeeeeeee444444444444IIIIIIIIIIIIWWWWWWWWWWWW))))))))))))''''''''''''}}}}}}}}}}}}",
"............eeeeeeeeeeee444444444444IIIIIIIIIIIIWWWWWWWWWWWW))))))))))))''''''''''''}}}}}}}}}}}}",
"............eeeeeeeeeeee444444444444IIIIIIIIIIIIWWWWWWWWWWWW))))))))))))''''''''''''}}}}}}}}}}}}",
"............eeeeeeeeeeee444444444444IIIIIIIIIIIIWWWWWWWWWWWW))))))))))))''''''''''''}}}}}}}}}}}}",
"............eeeeeeeeeeee444444444444IIIIIIIIIIIIWWWWWWWWWWWW))))))))))))''''''''''''}}}}}}}}}}}}",
"............eeeeeeeeeeee444444444444IIIIIIIIIIIIWWWWWWWWWWWW))))))))))))''''''''''''}}}}}}}}}}}}",
"............eeeeeeeeeeee444444444444IIIIIIIIIIIIWWWWWWWWWWWW))))))))))))''''''''''''}}}}}}}}}}}}",
"............eeeeeeeeeeee444444444444IIIIIIIIIIIIWWWWWWWWWWWW))))))))))))''''''''''''}}}}}}}}}}}}",
"............eeeeeeeeeeee444444444444IIIIIIIIIIIIWWWWWWWWWWWW))))))))))))''''''''''''}}}}}}}}}}}}",
"............eeeeeeeeeeee444444444444IIIIIIIIIIIIWWWWWWWWWWWW))))))))))))''''''''''''}}}}}}}}}}}}",
"llllllllllll444444444444HHHHHHHHHHHHvvvvvvvvvvvv((((((((((((____________]]]]]]]]]]]]}}}}}}}}}}}}",
"llllllllllll444444444444HHHHHHHHHHHHvvvvvvvvvvvv((((((((((((____________]]]]]]]]]]]]}}}}}}}}}}}}",
"llllllllllll444444444444HHHHHHHHHHHHvvvvvvvvvvvv((((((((((((____________]]]]]]]]]]]]}}}}}}}}}}}}",
"llllllllllll444444444444HHHHHHHHHHHHvvvvvvvvvvvv((((((((((((____________]]]]]]]]]]]]}}}}}}}}}}}}",
"llllllllllll444444444444HHHHHHHHHHHHvvvvvvvvvvvv((((((((((((____________]]]]]]]]]]]]}}}}}}}}}}}}",
"llllllllllll444444444444HHHHHHHHHHHHvvvvvvvvvvvv((((((((((((____________]]]]]]]]]]]]}}}}}}}}}}}}",
"llllllllllll444444444444HHHHHHHHHHHHvvvvvvvvvvvv((((((((((((____________]]]]]]]]]]]]}}}}}}}}}}}}",
"llllllllllll444444444444HHHHHHHHHHHHvvvvvvvvvvvv((((((((((((____________]]]]]]]]]]]]}}}}}}}}}}}}",
"llllllllllll444444444444HHHHHHHHHHHHvvvvvvvvvvvv((((((((((((____________]]]]]]]]]]]]}}}}}}}}}}}}",
"llllllllllll444444444444HHHHHHHHHHHHvvvvvvvvvvvv((((((((((((____________]]]]]]]]]]]]}}}}}}}}}}}}",
"llllllllllll444444444444HHHHHHHHHHHHvvvvvvvvvvvv((((((((((((____________]]]]]]]]]]]]}}}}}}}}}}}}",
"llllllllllll444444444444HHHHHHHHHHHHvvvvvvvvvvvv((((((((((((____________]]]]]]]]]]]]}}}}}}}}}}}}",
"qqqqqqqqqqqq111111111111ssssssssssssGGGGGGGGGGGGQQQQQQQQQQQQ____________[[[[[[[[[[[[{{{{{{{{{{{{",
"qqqqqqqqqqqq111111111111ssssssssssssGGGGGGGGGGGGQQQQQQQQQQQQ____________[[[[[[[[[[[[{{{{{{{{{{{{",
"qqqqqqqqqqqq111111111111ssssssssssssGGGGGGGGGGGGQQQQQQQQQQQQ____________[[[[[[[[[[[[{{{{{{{{{{{{",
"qqqqqqqqqqqq111111111111ssssssssssssGGGGGGGGGGGGQQQQQQQQQQQQ____________[[[[[[[[[[[[{{{{{{{{{{{{",
"qqqqqqqqqqqq111111111111ssssssssssssGGGGGGGGGGGGQQQQQQQQQQQQ____________[[[[[[[[[[[[{{{{{{{{{{{{",
"qqqqqqqqqqqq111111111111ssssssssssssGGGGGGGGGGGGQQQQQQQQQQQQ____________[[[[[[[[[[[[{{{{{{{{{{{{",
"qqqqqqqqqqqq111111111111ssssssssssssGGGGGGGGGGGGQQQQQQQQQQQQ____________[[[[[[[[[[[[{{{{{{{{{{{{",
"qqqqqqqqqqqq111111111111ssssssssssssGGGGGGGGGGGGQQQQQQQQQQQQ____________[[[[[[[[[[[[{{{{{{{{{{{{",
"qqqqqqqqqqqq111111111111ssssssssssssGGGGGGGGGGGGQQQQQQQQQQQQ____________[[[[[[[[[[[[{{{{{{{{{{{{",
"qqqqqqqqqqqq111111111111ssssssssssssGGGGGGGGGGGGQQQQQQQQQQQQ____________[[[[[[[[[[[[{{{{{{{{{{{{",
"qqqqqqqqqqqq111111111111ssssssssssssGGGGGGGGGGGGQQQQQQQQQQQQ____________[[[[[[[[[[[[{{{{{{{{{{{{",
"qqqqqqqqqqqq111111111111ssssssssssssGGGGGGGGGGGGQQQQQQQQQQQQ____________[[[[[[[[[[[[{{{{{{{{{{{{",
"ppppppppppppkkkkkkkkkkkkttttttttttttSSSSSSSSSSSS!!!!!!!!!!!!))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ppppppppppppkkkkkkkkkkkkttttttttttttSSSSSSSSSSSS!!!!!!!!!!!!))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ppppppppppppkkkkkkkkkkkkttttttttttttSSSSSSSSSSSS!!!!!!!!!!!!))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ppppppppppppkkkkkkkkkkkkttttttttttttSSSSSSSSSSSS!!!!!!!!!!!!))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ppppppppppppkkkkkkkkkkkkttttttttttttSSSSSSSSSSSS!!!!!!!!!!!!))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ppppppppppppkkkkkkkkkkkkttttttttttttSSSSSSSSSSSS!!!!!!!!!!!!))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ppppppppppppkkkkkkkkkkkkttttttttttttSSSSSSSSSSSS!!!!!!!!!!!!))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ppppppppppppkkkkkkkkkkkkttttttttttttSSSSSSSSSSSS!!!!!!!!!!!!))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ppppppppppppkkkkkkkkkkkkttttttttttttSSSSSSSSSSSS!!!!!!!!!!!!))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ppppppppppppkkkkkkkkkkkkttttttttttttSSSSSSSSSSSS!!!!!!!!!!!!))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ppppppppppppkkkkkkkkkkkkttttttttttttSSSSSSSSSSSS!!!!!!!!!!!!))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ppppppppppppkkkkkkkkkkkkttttttttttttSSSSSSSSSSSS!!!!!!!!!!!!))))))))))))]]]]]]]]]]]]{{{{{{{{{{{{",
"ppppppppppppzzzzzzzzzzzzddddddddddddFFFFFFFFFFFFLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{",
"ppppppppppppzzzzzzzzzzzzddddddddddddFFFFFFFFFFFFLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{",
"ppppppppppppzzzzzzzzzzzzddddddddddddFFFFFFFFFFFFLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{",
"ppppppppppppzzzzzzzzzzzzddddddddddddFFFFFFFFFFFFLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{",
"ppppppppppppzzzzzzzzzzzzddddddddddddFFFFFFFFFFFFLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{",
"ppppppppppppzzzzzzzzzzzzddddddddddddFFFFFFFFFFFFLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{",
"ppppppppppppzzzzzzzzzzzzddddddddddddFFFFFFFFFFFFLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{",
"ppppppppppppzzzzzzzzzzzzddddddddddddFFFFFFFFFFFFLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{",
"ppppppppppppzzzzzzzzzzzzddddddddddddFFFFFFFFFFFFLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{",
"ppppppppppppzzzzzzzzzzzzddddddddddddFFFFFFFFFFFFLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{",
"ppppppppppppzzzzzzzzzzzzddddddddddddFFFFFFFFFFFFLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{",
"ppppppppppppzzzzzzzzzzzzddddddddddddFFFFFFFFFFFFLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{",
"666666666666************777777777777MMMMMMMMMMMMLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{",
"666666666666************777777777777MMMMMMMMMMMMLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{",
"666666666666************777777777777MMMMMMMMMMMMLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{",
"666666666666************777777777777MMMMMMMMMMMMLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{",
"666666666666************777777777777MMMMMMMMMMMMLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{",
"666666666666************777777777777MMMMMMMMMMMMLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{",
"666666666666************777777777777MMMMMMMMMMMMLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{",
"666666666666************777777777777MMMMMMMMMMMMLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{",
"666666666666************777777777777MMMMMMMMMMMMLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{",
"666666666666************777777777777MMMMMMMMMMMMLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{",
"666666666666************777777777777MMMMMMMMMMMMLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{",
"666666666666************777777777777MMMMMMMMMMMMLLLLLLLLLLLL````````````''''''''''''{{{{{{{{{{{{"
};